From 0efda6c02a933c630c385df021fa15df18dd6e90 Mon Sep 17 00:00:00 2001 From: Enoch Date: Mon, 5 Aug 2024 22:57:28 +0800 Subject: [PATCH] save --- 404.html | 1 + acme | 1 + acme.sh | 0 cacme/.gitignore | 1 + cacme/LICENSE | 21 + cacme/README.md | 4 + cacme/app/command/Acme.php | 133 + cacme/app/controller/Apply.php | 27 + cacme/app/controller/IndexController.php | 13 + cacme/app/functions.php | 4 + cacme/app/middleware/StaticFile.php | 42 + cacme/app/model/Test.php | 29 + cacme/app/view/index.html | 183 + cacme/composer.json | 60 + cacme/composer.lock | 2516 ++++ cacme/config/app.php | 26 + cacme/config/autoload.php | 21 + cacme/config/bootstrap.php | 18 + cacme/config/container.php | 15 + cacme/config/database.php | 15 + cacme/config/dependence.php | 15 + cacme/config/exception.php | 17 + cacme/config/log.php | 32 + cacme/config/middleware.php | 15 + cacme/config/plugin/webman/console/app.php | 24 + cacme/config/process.php | 42 + cacme/config/redis.php | 22 + cacme/config/route.php | 22 + cacme/config/server.php | 31 + cacme/config/session.php | 65 + cacme/config/static.php | 23 + cacme/config/translation.php | 25 + cacme/config/view.php | 22 + cacme/process/Monitor.php | 243 + cacme/public/404.html | 12 + cacme/public/favicon.ico | Bin 0 -> 4286 bytes cacme/public/jquery-3.7.1.js | 10716 ++++++++++++++++ cacme/public/normal.css | 461 + cacme/public/sakura.css | 225 + cacme/runtime/.gitignore | 4 + cacme/runtime/logs/.gitignore | 2 + cacme/runtime/views/.gitignore | 2 + cacme/start.php | 4 + cacme/support/Request.php | 24 + cacme/support/Response.php | 24 + cacme/support/bootstrap.php | 133 + cacme/support/helpers.php | 528 + cacme/vendor/acmephp/core/.gitignore | 2 + cacme/vendor/acmephp/core/AcmeClient.php | 404 + .../acmephp/core/AcmeClientInterface.php | 187 + .../acmephp/core/Challenge/ChainValidator.php | 62 + .../ConfigurableServiceInterface.php | 25 + .../core/Challenge/Dns/DnsDataExtractor.php | 47 + .../Challenge/Dns/DnsResolverInterface.php | 30 + .../core/Challenge/Dns/DnsValidator.php | 68 + .../core/Challenge/Dns/GandiSolver.php | 152 + .../core/Challenge/Dns/LibDnsResolver.php | 200 + .../core/Challenge/Dns/Route53Solver.php | 295 + .../core/Challenge/Dns/SimpleDnsResolver.php | 43 + .../core/Challenge/Dns/SimpleDnsSolver.php | 100 + .../core/Challenge/Http/FilesystemSolver.php | 90 + .../core/Challenge/Http/HttpDataExtractor.php | 53 + .../core/Challenge/Http/HttpValidator.php | 65 + .../core/Challenge/Http/MockHttpValidator.php | 40 + .../Challenge/Http/MockServerHttpSolver.php | 58 + .../core/Challenge/Http/SimpleHttpSolver.php | 96 + .../MultipleChallengesSolverInterface.php | 36 + .../core/Challenge/SolverInterface.php | 39 + .../core/Challenge/ValidatorInterface.php | 36 + .../core/Challenge/WaitingValidator.php | 60 + .../Exception/AcmeCoreClientException.php | 25 + .../core/Exception/AcmeCoreException.php | 19 + .../Exception/AcmeCoreServerException.php | 27 + .../Exception/AcmeDnsResolutionException.php | 23 + .../CertificateRequestFailedException.php | 23 + .../CertificateRequestTimedOutException.php | 23 + .../CertificateRevocationException.php | 18 + .../Protocol/ChallengeFailedException.php | 38 + .../ChallengeNotSupportedException.php | 23 + .../Protocol/ChallengeTimedOutException.php | 38 + .../Protocol/ExpectedJsonException.php | 19 + .../Exception/Protocol/ProtocolException.php | 23 + .../Server/BadCsrServerException.php | 30 + .../Server/BadNonceServerException.php | 30 + .../Exception/Server/CaaServerException.php | 30 + .../Server/ConnectionServerException.php | 30 + .../Exception/Server/DnsServerException.php | 30 + .../IncorrectResponseServerException.php | 30 + .../Server/InternalServerException.php | 30 + .../Server/InvalidContactServerException.php | 30 + .../Server/InvalidEmailServerException.php | 30 + .../Server/MalformedServerException.php | 30 + .../Server/OrderNotReadyServerException.php | 27 + .../Server/RateLimitedServerException.php | 30 + .../RejectedIdentifierServerException.php | 30 + .../Exception/Server/TlsServerException.php | 30 + .../Server/UnauthorizedServerException.php | 30 + .../Server/UnknownHostServerException.php | 30 + .../UnsupportedContactServerException.php | 30 + .../UnsupportedIdentifierServerException.php | 30 + .../UserActionRequiredServerException.php | 30 + .../Filesystem/Adapter/FlysystemAdapter.php | 67 + .../Adapter/FlysystemFtpFactory.php | 28 + .../Adapter/FlysystemLocalFactory.php | 31 + .../Adapter/FlysystemSftpFactory.php | 28 + .../core/Filesystem/Adapter/NullAdapter.php | 23 + .../Filesystem/FilesystemFactoryInterface.php | 20 + .../core/Filesystem/FilesystemInterface.php | 30 + .../acmephp/core/Http/Base64SafeEncoder.php | 37 + .../acmephp/core/Http/SecureHttpClient.php | 421 + .../core/Http/SecureHttpClientFactory.php | 79 + .../acmephp/core/Http/ServerErrorHandler.php | 144 + cacme/vendor/acmephp/core/LICENSE | 22 + .../core/Protocol/AuthorizationChallenge.php | 112 + .../core/Protocol/CertificateOrder.php | 102 + .../acmephp/core/Protocol/ExternalAccount.php | 42 + .../core/Protocol/ResourcesDirectory.php | 62 + .../core/Protocol/RevocationReason.php | 79 + cacme/vendor/acmephp/core/README.md | 35 + .../vendor/acmephp/core/Util/JsonDecoder.php | 49 + cacme/vendor/acmephp/core/composer.json | 50 + cacme/vendor/acmephp/ssl/.gitignore | 2 + cacme/vendor/acmephp/ssl/Certificate.php | 80 + .../vendor/acmephp/ssl/CertificateRequest.php | 42 + .../acmephp/ssl/CertificateResponse.php | 42 + .../vendor/acmephp/ssl/DistinguishedName.php | 112 + .../ssl/Exception/AcmeSslException.php | 19 + .../ssl/Exception/CSRSigningException.php | 19 + .../Exception/CertificateFormatException.php | 19 + .../Exception/CertificateParsingException.php | 19 + .../ssl/Exception/DataSigningException.php | 19 + .../ssl/Exception/KeyFormatException.php | 19 + .../ssl/Exception/KeyGenerationException.php | 19 + .../Exception/KeyPairGenerationException.php | 19 + .../ssl/Exception/KeyParsingException.php | 19 + .../ssl/Exception/ParsingException.php | 19 + .../ssl/Exception/SigningException.php | 19 + .../Generator/ChainPrivateKeyGenerator.php | 55 + .../ssl/Generator/DhKey/DhKeyGenerator.php | 46 + .../ssl/Generator/DhKey/DhKeyOption.php | 45 + .../ssl/Generator/DsaKey/DsaKeyGenerator.php | 43 + .../ssl/Generator/DsaKey/DsaKeyOption.php | 30 + .../ssl/Generator/EcKey/EcKeyGenerator.php | 43 + .../ssl/Generator/EcKey/EcKeyOption.php | 33 + .../acmephp/ssl/Generator/KeyOption.php | 16 + .../ssl/Generator/KeyPairGenerator.php | 66 + .../OpensslPrivateKeyGeneratorTrait.php | 38 + .../PrivateKeyGeneratorInterface.php | 39 + .../ssl/Generator/RsaKey/RsaKeyGenerator.php | 43 + .../ssl/Generator/RsaKey/RsaKeyOption.php | 30 + cacme/vendor/acmephp/ssl/Key.php | 53 + cacme/vendor/acmephp/ssl/KeyPair.php | 42 + cacme/vendor/acmephp/ssl/LICENSE | 22 + .../vendor/acmephp/ssl/ParsedCertificate.php | 123 + cacme/vendor/acmephp/ssl/ParsedKey.php | 92 + .../acmephp/ssl/Parser/CertificateParser.php | 76 + cacme/vendor/acmephp/ssl/Parser/KeyParser.php | 65 + cacme/vendor/acmephp/ssl/PrivateKey.php | 63 + cacme/vendor/acmephp/ssl/PublicKey.php | 53 + cacme/vendor/acmephp/ssl/README.md | 36 + .../ssl/Signer/CertificateRequestSigner.php | 130 + .../vendor/acmephp/ssl/Signer/DataSigner.php | 118 + cacme/vendor/acmephp/ssl/composer.json | 44 + cacme/vendor/autoload.php | 25 + cacme/vendor/composer/ClassLoader.php | 579 + cacme/vendor/composer/InstalledVersions.php | 359 + cacme/vendor/composer/LICENSE | 21 + cacme/vendor/composer/autoload_classmap.php | 11 + cacme/vendor/composer/autoload_files.php | 20 + cacme/vendor/composer/autoload_namespaces.php | 9 + cacme/vendor/composer/autoload_psr4.php | 48 + cacme/vendor/composer/autoload_real.php | 50 + cacme/vendor/composer/autoload_static.php | 278 + cacme/vendor/composer/installed.json | 2600 ++++ cacme/vendor/composer/installed.php | 345 + cacme/vendor/composer/platform_check.php | 26 + cacme/vendor/doctrine/inflector/LICENSE | 19 + cacme/vendor/doctrine/inflector/README.md | 7 + cacme/vendor/doctrine/inflector/composer.json | 41 + .../doctrine/inflector/docs/en/index.rst | 226 + .../Inflector/CachedWordInflector.php | 24 + .../GenericLanguageInflectorFactory.php | 66 + .../lib/Doctrine/Inflector/Inflector.php | 507 + .../Doctrine/Inflector/InflectorFactory.php | 52 + .../lib/Doctrine/Inflector/Language.php | 19 + .../Inflector/LanguageInflectorFactory.php | 33 + .../Doctrine/Inflector/NoopWordInflector.php | 13 + .../Inflector/Rules/English/Inflectible.php | 184 + .../Rules/English/InflectorFactory.php | 21 + .../Inflector/Rules/English/Rules.php | 31 + .../Inflector/Rules/English/Uninflected.php | 189 + .../Inflector/Rules/French/Inflectible.php | 44 + .../Rules/French/InflectorFactory.php | 21 + .../Doctrine/Inflector/Rules/French/Rules.php | 31 + .../Inflector/Rules/French/Uninflected.php | 28 + .../Rules/NorwegianBokmal/Inflectible.php | 34 + .../NorwegianBokmal/InflectorFactory.php | 21 + .../Inflector/Rules/NorwegianBokmal/Rules.php | 31 + .../Rules/NorwegianBokmal/Uninflected.php | 30 + .../lib/Doctrine/Inflector/Rules/Pattern.php | 42 + .../lib/Doctrine/Inflector/Rules/Patterns.php | 34 + .../Rules/Portuguese/Inflectible.php | 98 + .../Rules/Portuguese/InflectorFactory.php | 21 + .../Inflector/Rules/Portuguese/Rules.php | 31 + .../Rules/Portuguese/Uninflected.php | 32 + .../lib/Doctrine/Inflector/Rules/Ruleset.php | 39 + .../Inflector/Rules/Spanish/Inflectible.php | 47 + .../Rules/Spanish/InflectorFactory.php | 21 + .../Inflector/Rules/Spanish/Rules.php | 31 + .../Inflector/Rules/Spanish/Uninflected.php | 30 + .../Doctrine/Inflector/Rules/Substitution.php | 30 + .../Inflector/Rules/Substitutions.php | 57 + .../Inflector/Rules/Transformation.php | 39 + .../Inflector/Rules/Transformations.php | 29 + .../Inflector/Rules/Turkish/Inflectible.php | 34 + .../Rules/Turkish/InflectorFactory.php | 21 + .../Inflector/Rules/Turkish/Rules.php | 31 + .../Inflector/Rules/Turkish/Uninflected.php | 30 + .../lib/Doctrine/Inflector/Rules/Word.php | 21 + .../Doctrine/Inflector/RulesetInflector.php | 56 + .../lib/Doctrine/Inflector/WordInflector.php | 10 + cacme/vendor/guzzlehttp/guzzle/CHANGELOG.md | 1633 +++ cacme/vendor/guzzlehttp/guzzle/LICENSE | 27 + cacme/vendor/guzzlehttp/guzzle/README.md | 94 + cacme/vendor/guzzlehttp/guzzle/UPGRADING.md | 1253 ++ cacme/vendor/guzzlehttp/guzzle/composer.json | 103 + .../guzzlehttp/guzzle/src/BodySummarizer.php | 28 + .../guzzle/src/BodySummarizerInterface.php | 13 + cacme/vendor/guzzlehttp/guzzle/src/Client.php | 483 + .../guzzlehttp/guzzle/src/ClientInterface.php | 84 + .../guzzlehttp/guzzle/src/ClientTrait.php | 241 + .../guzzle/src/Cookie/CookieJar.php | 307 + .../guzzle/src/Cookie/CookieJarInterface.php | 80 + .../guzzle/src/Cookie/FileCookieJar.php | 101 + .../guzzle/src/Cookie/SessionCookieJar.php | 77 + .../guzzle/src/Cookie/SetCookie.php | 488 + .../src/Exception/BadResponseException.php | 39 + .../guzzle/src/Exception/ClientException.php | 10 + .../guzzle/src/Exception/ConnectException.php | 56 + .../guzzle/src/Exception/GuzzleException.php | 9 + .../Exception/InvalidArgumentException.php | 7 + .../guzzle/src/Exception/RequestException.php | 166 + .../guzzle/src/Exception/ServerException.php | 10 + .../Exception/TooManyRedirectsException.php | 7 + .../src/Exception/TransferException.php | 7 + .../guzzle/src/Handler/CurlFactory.php | 638 + .../src/Handler/CurlFactoryInterface.php | 25 + .../guzzle/src/Handler/CurlHandler.php | 49 + .../guzzle/src/Handler/CurlMultiHandler.php | 267 + .../guzzle/src/Handler/EasyHandle.php | 112 + .../guzzle/src/Handler/HeaderProcessor.php | 42 + .../guzzle/src/Handler/MockHandler.php | 212 + .../guzzlehttp/guzzle/src/Handler/Proxy.php | 51 + .../guzzle/src/Handler/StreamHandler.php | 615 + .../guzzlehttp/guzzle/src/HandlerStack.php | 275 + .../guzzle/src/MessageFormatter.php | 199 + .../guzzle/src/MessageFormatterInterface.php | 18 + .../guzzlehttp/guzzle/src/Middleware.php | 268 + cacme/vendor/guzzlehttp/guzzle/src/Pool.php | 125 + .../guzzle/src/PrepareBodyMiddleware.php | 105 + .../guzzle/src/RedirectMiddleware.php | 228 + .../guzzlehttp/guzzle/src/RequestOptions.php | 274 + .../guzzlehttp/guzzle/src/RetryMiddleware.php | 119 + .../guzzlehttp/guzzle/src/TransferStats.php | 133 + cacme/vendor/guzzlehttp/guzzle/src/Utils.php | 384 + .../guzzlehttp/guzzle/src/functions.php | 167 + .../guzzle/src/functions_include.php | 6 + cacme/vendor/guzzlehttp/promises/CHANGELOG.md | 152 + cacme/vendor/guzzlehttp/promises/LICENSE | 24 + cacme/vendor/guzzlehttp/promises/README.md | 559 + .../vendor/guzzlehttp/promises/composer.json | 58 + .../promises/src/AggregateException.php | 19 + .../promises/src/CancellationException.php | 12 + .../guzzlehttp/promises/src/Coroutine.php | 162 + .../vendor/guzzlehttp/promises/src/Create.php | 79 + cacme/vendor/guzzlehttp/promises/src/Each.php | 81 + .../guzzlehttp/promises/src/EachPromise.php | 248 + .../promises/src/FulfilledPromise.php | 89 + cacme/vendor/guzzlehttp/promises/src/Is.php | 40 + .../guzzlehttp/promises/src/Promise.php | 281 + .../promises/src/PromiseInterface.php | 91 + .../promises/src/PromisorInterface.php | 16 + .../promises/src/RejectedPromise.php | 95 + .../promises/src/RejectionException.php | 49 + .../guzzlehttp/promises/src/TaskQueue.php | 71 + .../promises/src/TaskQueueInterface.php | 24 + .../vendor/guzzlehttp/promises/src/Utils.php | 259 + cacme/vendor/guzzlehttp/psr7/CHANGELOG.md | 448 + cacme/vendor/guzzlehttp/psr7/LICENSE | 26 + cacme/vendor/guzzlehttp/psr7/README.md | 880 ++ cacme/vendor/guzzlehttp/psr7/composer.json | 93 + .../guzzlehttp/psr7/src/AppendStream.php | 248 + .../guzzlehttp/psr7/src/BufferStream.php | 147 + .../guzzlehttp/psr7/src/CachingStream.php | 153 + .../guzzlehttp/psr7/src/DroppingStream.php | 49 + .../src/Exception/MalformedUriException.php | 14 + cacme/vendor/guzzlehttp/psr7/src/FnStream.php | 180 + cacme/vendor/guzzlehttp/psr7/src/Header.php | 134 + .../guzzlehttp/psr7/src/HttpFactory.php | 94 + .../guzzlehttp/psr7/src/InflateStream.php | 37 + .../guzzlehttp/psr7/src/LazyOpenStream.php | 49 + .../guzzlehttp/psr7/src/LimitStream.php | 157 + cacme/vendor/guzzlehttp/psr7/src/Message.php | 246 + .../guzzlehttp/psr7/src/MessageTrait.php | 265 + cacme/vendor/guzzlehttp/psr7/src/MimeType.php | 1259 ++ .../guzzlehttp/psr7/src/MultipartStream.php | 165 + .../guzzlehttp/psr7/src/NoSeekStream.php | 28 + .../vendor/guzzlehttp/psr7/src/PumpStream.php | 179 + cacme/vendor/guzzlehttp/psr7/src/Query.php | 113 + cacme/vendor/guzzlehttp/psr7/src/Request.php | 159 + cacme/vendor/guzzlehttp/psr7/src/Response.php | 161 + cacme/vendor/guzzlehttp/psr7/src/Rfc7230.php | 23 + .../guzzlehttp/psr7/src/ServerRequest.php | 340 + cacme/vendor/guzzlehttp/psr7/src/Stream.php | 283 + .../psr7/src/StreamDecoratorTrait.php | 156 + .../guzzlehttp/psr7/src/StreamWrapper.php | 203 + .../guzzlehttp/psr7/src/UploadedFile.php | 211 + cacme/vendor/guzzlehttp/psr7/src/Uri.php | 743 ++ .../guzzlehttp/psr7/src/UriComparator.php | 52 + .../guzzlehttp/psr7/src/UriNormalizer.php | 220 + .../guzzlehttp/psr7/src/UriResolver.php | 211 + cacme/vendor/guzzlehttp/psr7/src/Utils.php | 463 + cacme/vendor/lcobucci/clock/LICENSE | 21 + cacme/vendor/lcobucci/clock/composer.json | 40 + cacme/vendor/lcobucci/clock/src/Clock.php | 12 + .../vendor/lcobucci/clock/src/FrozenClock.php | 29 + .../vendor/lcobucci/clock/src/SystemClock.php | 31 + cacme/vendor/lcobucci/jwt/LICENSE | 27 + cacme/vendor/lcobucci/jwt/composer.json | 66 + cacme/vendor/lcobucci/jwt/src/Builder.php | 77 + .../lcobucci/jwt/src/ClaimsFormatter.php | 14 + .../vendor/lcobucci/jwt/src/Configuration.php | 155 + cacme/vendor/lcobucci/jwt/src/Decoder.php | 27 + cacme/vendor/lcobucci/jwt/src/Encoder.php | 25 + .../jwt/src/Encoding/CannotDecodeContent.php | 21 + .../jwt/src/Encoding/CannotEncodeContent.php | 16 + .../jwt/src/Encoding/ChainedFormatter.php | 37 + .../lcobucci/jwt/src/Encoding/JoseEncoder.php | 60 + .../MicrosecondBasedDateConversion.php | 37 + .../jwt/src/Encoding/UnifyAudience.php | 29 + .../jwt/src/Encoding/UnixTimestampDates.php | 32 + cacme/vendor/lcobucci/jwt/src/Exception.php | 10 + cacme/vendor/lcobucci/jwt/src/JwtFacade.php | 66 + cacme/vendor/lcobucci/jwt/src/Parser.php | 20 + cacme/vendor/lcobucci/jwt/src/Signer.php | 34 + .../lcobucci/jwt/src/Signer/Blake2b.php | 36 + .../jwt/src/Signer/CannotSignPayload.php | 15 + .../vendor/lcobucci/jwt/src/Signer/Ecdsa.php | 69 + .../jwt/src/Signer/Ecdsa/ConversionFailed.php | 25 + .../Signer/Ecdsa/MultibyteStringConverter.php | 146 + .../lcobucci/jwt/src/Signer/Ecdsa/Sha256.php | 31 + .../lcobucci/jwt/src/Signer/Ecdsa/Sha384.php | 31 + .../lcobucci/jwt/src/Signer/Ecdsa/Sha512.php | 31 + .../src/Signer/Ecdsa/SignatureConverter.php | 34 + .../jwt/src/Signer/Ecdsa/UnsafeSha256.php | 27 + .../jwt/src/Signer/Ecdsa/UnsafeSha384.php | 27 + .../jwt/src/Signer/Ecdsa/UnsafeSha512.php | 27 + .../vendor/lcobucci/jwt/src/Signer/Eddsa.php | 36 + cacme/vendor/lcobucci/jwt/src/Signer/Hmac.php | 34 + .../lcobucci/jwt/src/Signer/Hmac/Sha256.php | 24 + .../lcobucci/jwt/src/Signer/Hmac/Sha384.php | 24 + .../lcobucci/jwt/src/Signer/Hmac/Sha512.php | 24 + .../jwt/src/Signer/Hmac/UnsafeSha256.php | 25 + .../jwt/src/Signer/Hmac/UnsafeSha384.php | 25 + .../jwt/src/Signer/Hmac/UnsafeSha512.php | 25 + .../jwt/src/Signer/InvalidKeyProvided.php | 42 + cacme/vendor/lcobucci/jwt/src/Signer/Key.php | 11 + .../jwt/src/Signer/Key/FileCouldNotBeRead.php | 20 + .../lcobucci/jwt/src/Signer/Key/InMemory.php | 85 + .../jwt/src/Signer/Key/LocalFileReference.php | 54 + cacme/vendor/lcobucci/jwt/src/Signer/None.php | 27 + .../lcobucci/jwt/src/Signer/OpenSSL.php | 154 + cacme/vendor/lcobucci/jwt/src/Signer/Rsa.php | 35 + .../lcobucci/jwt/src/Signer/Rsa/Sha256.php | 21 + .../lcobucci/jwt/src/Signer/Rsa/Sha384.php | 21 + .../lcobucci/jwt/src/Signer/Rsa/Sha512.php | 21 + .../jwt/src/Signer/Rsa/UnsafeSha256.php | 22 + .../jwt/src/Signer/Rsa/UnsafeSha384.php | 22 + .../jwt/src/Signer/Rsa/UnsafeSha512.php | 22 + .../lcobucci/jwt/src/Signer/UnsafeEcdsa.php | 60 + .../lcobucci/jwt/src/Signer/UnsafeRsa.php | 31 + .../lcobucci/jwt/src/SodiumBase64Polyfill.php | 88 + cacme/vendor/lcobucci/jwt/src/Token.php | 55 + .../vendor/lcobucci/jwt/src/Token/Builder.php | 128 + .../vendor/lcobucci/jwt/src/Token/DataSet.php | 46 + .../jwt/src/Token/InvalidTokenStructure.php | 25 + .../vendor/lcobucci/jwt/src/Token/Parser.php | 154 + cacme/vendor/lcobucci/jwt/src/Token/Plain.php | 92 + .../jwt/src/Token/RegisteredClaimGiven.php | 20 + .../jwt/src/Token/RegisteredClaims.php | 77 + .../lcobucci/jwt/src/Token/Signature.php | 35 + .../jwt/src/Token/UnsupportedHeaderFound.php | 15 + .../lcobucci/jwt/src/UnencryptedToken.php | 25 + .../jwt/src/Validation/Constraint.php | 12 + .../CannotValidateARegisteredClaim.php | 17 + .../Constraint/HasClaimWithValue.php | 50 + .../Validation/Constraint/IdentifiedBy.php | 28 + .../src/Validation/Constraint/IssuedBy.php | 29 + .../Constraint/LeewayCannotBeNegative.php | 15 + .../Validation/Constraint/LooseValidAt.php | 69 + .../Validation/Constraint/PermittedFor.php | 28 + .../src/Validation/Constraint/RelatedTo.php | 28 + .../src/Validation/Constraint/SignedWith.php | 37 + .../Validation/Constraint/StrictValidAt.php | 86 + .../jwt/src/Validation/Constraint/ValidAt.php | 25 + .../src/Validation/ConstraintViolation.php | 26 + .../jwt/src/Validation/NoConstraintsGiven.php | 11 + .../RequiredConstraintsViolated.php | 46 + .../jwt/src/Validation/SignedWith.php | 8 + .../lcobucci/jwt/src/Validation/ValidAt.php | 8 + .../lcobucci/jwt/src/Validation/Validator.php | 56 + cacme/vendor/lcobucci/jwt/src/Validator.php | 20 + cacme/vendor/monolog/monolog/CHANGELOG.md | 629 + cacme/vendor/monolog/monolog/LICENSE | 19 + cacme/vendor/monolog/monolog/README.md | 112 + cacme/vendor/monolog/monolog/UPGRADE.md | 72 + cacme/vendor/monolog/monolog/composer.json | 81 + .../Monolog/Attribute/AsMonologProcessor.php | 46 + .../monolog/src/Monolog/DateTimeImmutable.php | 49 + .../monolog/src/Monolog/ErrorHandler.php | 307 + .../Monolog/Formatter/ChromePHPFormatter.php | 83 + .../Monolog/Formatter/ElasticaFormatter.php | 89 + .../Formatter/ElasticsearchFormatter.php | 89 + .../Monolog/Formatter/FlowdockFormatter.php | 112 + .../Monolog/Formatter/FluentdFormatter.php | 88 + .../Monolog/Formatter/FormatterInterface.php | 42 + .../Formatter/GelfMessageFormatter.php | 175 + .../Formatter/GoogleCloudLoggingFormatter.php | 40 + .../src/Monolog/Formatter/HtmlFormatter.php | 142 + .../src/Monolog/Formatter/JsonFormatter.php | 224 + .../src/Monolog/Formatter/LineFormatter.php | 246 + .../src/Monolog/Formatter/LogglyFormatter.php | 45 + .../Monolog/Formatter/LogmaticFormatter.php | 66 + .../Monolog/Formatter/LogstashFormatter.php | 101 + .../Monolog/Formatter/MongoDBFormatter.php | 162 + .../Monolog/Formatter/NormalizerFormatter.php | 290 + .../src/Monolog/Formatter/ScalarFormatter.php | 51 + .../Monolog/Formatter/WildfireFormatter.php | 139 + .../src/Monolog/Handler/AbstractHandler.php | 112 + .../Handler/AbstractProcessingHandler.php | 69 + .../Monolog/Handler/AbstractSyslogHandler.php | 106 + .../src/Monolog/Handler/AmqpHandler.php | 171 + .../Monolog/Handler/BrowserConsoleHandler.php | 308 + .../src/Monolog/Handler/BufferHandler.php | 167 + .../src/Monolog/Handler/ChromePHPHandler.php | 196 + .../src/Monolog/Handler/CouchDBHandler.php | 77 + .../src/Monolog/Handler/CubeHandler.php | 167 + .../monolog/src/Monolog/Handler/Curl/Util.php | 71 + .../Monolog/Handler/DeduplicationHandler.php | 186 + .../Handler/DoctrineCouchDBHandler.php | 47 + .../src/Monolog/Handler/DynamoDbHandler.php | 104 + .../src/Monolog/Handler/ElasticaHandler.php | 129 + .../Monolog/Handler/ElasticsearchHandler.php | 218 + .../src/Monolog/Handler/ErrorLogHandler.php | 91 + .../Monolog/Handler/FallbackGroupHandler.php | 71 + .../src/Monolog/Handler/FilterHandler.php | 212 + .../ActivationStrategyInterface.php | 29 + .../ChannelLevelActivationStrategy.php | 77 + .../ErrorLevelActivationStrategy.php | 46 + .../Monolog/Handler/FingersCrossedHandler.php | 252 + .../src/Monolog/Handler/FirePHPHandler.php | 180 + .../src/Monolog/Handler/FleepHookHandler.php | 135 + .../src/Monolog/Handler/FlowdockHandler.php | 133 + .../Handler/FormattableHandlerInterface.php | 37 + .../Handler/FormattableHandlerTrait.php | 60 + .../src/Monolog/Handler/GelfHandler.php | 57 + .../src/Monolog/Handler/GroupHandler.php | 132 + .../monolog/src/Monolog/Handler/Handler.php | 62 + .../src/Monolog/Handler/HandlerInterface.php | 85 + .../src/Monolog/Handler/HandlerWrapper.php | 136 + .../src/Monolog/Handler/IFTTTHandler.php | 74 + .../src/Monolog/Handler/InsightOpsHandler.php | 76 + .../src/Monolog/Handler/LogEntriesHandler.php | 70 + .../src/Monolog/Handler/LogglyHandler.php | 160 + .../src/Monolog/Handler/LogmaticHandler.php | 106 + .../src/Monolog/Handler/MailHandler.php | 95 + .../src/Monolog/Handler/MandrillHandler.php | 83 + .../Handler/MissingExtensionException.php | 21 + .../src/Monolog/Handler/MongoDBHandler.php | 86 + .../Monolog/Handler/NativeMailerHandler.php | 174 + .../src/Monolog/Handler/NewRelicHandler.php | 199 + .../src/Monolog/Handler/NoopHandler.php | 40 + .../src/Monolog/Handler/NullHandler.php | 60 + .../src/Monolog/Handler/OverflowHandler.php | 149 + .../src/Monolog/Handler/PHPConsoleHandler.php | 263 + .../src/Monolog/Handler/ProcessHandler.php | 191 + .../Handler/ProcessableHandlerInterface.php | 44 + .../Handler/ProcessableHandlerTrait.php | 77 + .../src/Monolog/Handler/PsrHandler.php | 95 + .../src/Monolog/Handler/PushoverHandler.php | 246 + .../src/Monolog/Handler/RedisHandler.php | 101 + .../Monolog/Handler/RedisPubSubHandler.php | 67 + .../src/Monolog/Handler/RollbarHandler.php | 131 + .../Monolog/Handler/RotatingFileHandler.php | 207 + .../src/Monolog/Handler/SamplingHandler.php | 132 + .../src/Monolog/Handler/SendGridHandler.php | 102 + .../src/Monolog/Handler/Slack/SlackRecord.php | 387 + .../src/Monolog/Handler/SlackHandler.php | 256 + .../Monolog/Handler/SlackWebhookHandler.php | 130 + .../src/Monolog/Handler/SocketHandler.php | 448 + .../src/Monolog/Handler/SqsHandler.php | 62 + .../src/Monolog/Handler/StreamHandler.php | 224 + .../Monolog/Handler/SwiftMailerHandler.php | 115 + .../Monolog/Handler/SymfonyMailerHandler.php | 111 + .../src/Monolog/Handler/SyslogHandler.php | 68 + .../Monolog/Handler/SyslogUdp/UdpSocket.php | 88 + .../src/Monolog/Handler/SyslogUdpHandler.php | 150 + .../Monolog/Handler/TelegramBotHandler.php | 274 + .../src/Monolog/Handler/TestHandler.php | 231 + .../Handler/WebRequestRecognizerTrait.php | 24 + .../Handler/WhatFailureGroupHandler.php | 81 + .../Monolog/Handler/ZendMonitorHandler.php | 101 + .../monolog/monolog/src/Monolog/LogRecord.php | 34 + .../monolog/monolog/src/Monolog/Logger.php | 761 ++ .../src/Monolog/Processor/GitProcessor.php | 77 + .../Monolog/Processor/HostnameProcessor.php | 36 + .../Processor/IntrospectionProcessor.php | 123 + .../Processor/MemoryPeakUsageProcessor.php | 37 + .../src/Monolog/Processor/MemoryProcessor.php | 61 + .../Processor/MemoryUsageProcessor.php | 37 + .../Monolog/Processor/MercurialProcessor.php | 77 + .../Monolog/Processor/ProcessIdProcessor.php | 30 + .../Monolog/Processor/ProcessorInterface.php | 30 + .../Processor/PsrLogMessageProcessor.php | 88 + .../src/Monolog/Processor/TagProcessor.php | 61 + .../src/Monolog/Processor/UidProcessor.php | 59 + .../src/Monolog/Processor/WebProcessor.php | 111 + .../monolog/monolog/src/Monolog/Registry.php | 134 + .../src/Monolog/ResettableInterface.php | 34 + .../monolog/src/Monolog/SignalHandler.php | 120 + .../monolog/src/Monolog/Test/TestCase.php | 85 + .../monolog/monolog/src/Monolog/Utils.php | 284 + cacme/vendor/nikic/fast-route/.gitignore | 5 + cacme/vendor/nikic/fast-route/.hhconfig | 1 + cacme/vendor/nikic/fast-route/.travis.yml | 20 + cacme/vendor/nikic/fast-route/FastRoute.hhi | 126 + cacme/vendor/nikic/fast-route/LICENSE | 31 + cacme/vendor/nikic/fast-route/README.md | 313 + cacme/vendor/nikic/fast-route/composer.json | 24 + cacme/vendor/nikic/fast-route/phpunit.xml | 24 + cacme/vendor/nikic/fast-route/psalm.xml | 28 + .../fast-route/src/BadRouteException.php | 7 + .../nikic/fast-route/src/DataGenerator.php | 26 + .../src/DataGenerator/CharCountBased.php | 31 + .../src/DataGenerator/GroupCountBased.php | 30 + .../src/DataGenerator/GroupPosBased.php | 27 + .../src/DataGenerator/MarkBased.php | 27 + .../src/DataGenerator/RegexBasedAbstract.php | 186 + .../nikic/fast-route/src/Dispatcher.php | 26 + .../src/Dispatcher/CharCountBased.php | 31 + .../src/Dispatcher/GroupCountBased.php | 31 + .../src/Dispatcher/GroupPosBased.php | 33 + .../fast-route/src/Dispatcher/MarkBased.php | 31 + .../src/Dispatcher/RegexBasedAbstract.php | 88 + cacme/vendor/nikic/fast-route/src/Route.php | 47 + .../nikic/fast-route/src/RouteCollector.php | 152 + .../nikic/fast-route/src/RouteParser.php | 37 + .../nikic/fast-route/src/RouteParser/Std.php | 87 + .../vendor/nikic/fast-route/src/bootstrap.php | 12 + .../vendor/nikic/fast-route/src/functions.php | 74 + .../test/Dispatcher/CharCountBasedTest.php | 16 + .../test/Dispatcher/DispatcherTest.php | 581 + .../test/Dispatcher/GroupCountBasedTest.php | 16 + .../test/Dispatcher/GroupPosBasedTest.php | 16 + .../test/Dispatcher/MarkBasedTest.php | 24 + .../HackTypechecker/HackTypecheckerTest.php | 44 + .../HackTypechecker/fixtures/all_options.php | 29 + .../fixtures/empty_options.php | 11 + .../HackTypechecker/fixtures/no_options.php | 11 + .../fast-route/test/RouteCollectorTest.php | 108 + .../fast-route/test/RouteParser/StdTest.php | 154 + .../nikic/fast-route/test/bootstrap.php | 11 + cacme/vendor/psr/clock/CHANGELOG.md | 11 + cacme/vendor/psr/clock/LICENSE | 19 + cacme/vendor/psr/clock/README.md | 61 + cacme/vendor/psr/clock/composer.json | 21 + cacme/vendor/psr/clock/src/ClockInterface.php | 13 + cacme/vendor/psr/container/.gitignore | 3 + cacme/vendor/psr/container/LICENSE | 21 + cacme/vendor/psr/container/README.md | 13 + cacme/vendor/psr/container/composer.json | 27 + .../src/ContainerExceptionInterface.php | 12 + .../psr/container/src/ContainerInterface.php | 36 + .../src/NotFoundExceptionInterface.php | 10 + cacme/vendor/psr/http-client/CHANGELOG.md | 31 + cacme/vendor/psr/http-client/LICENSE | 19 + cacme/vendor/psr/http-client/README.md | 12 + cacme/vendor/psr/http-client/composer.json | 30 + .../src/ClientExceptionInterface.php | 10 + .../psr/http-client/src/ClientInterface.php | 20 + .../src/NetworkExceptionInterface.php | 24 + .../src/RequestExceptionInterface.php | 24 + cacme/vendor/psr/http-factory/LICENSE | 21 + cacme/vendor/psr/http-factory/README.md | 12 + cacme/vendor/psr/http-factory/composer.json | 35 + .../src/RequestFactoryInterface.php | 18 + .../src/ResponseFactoryInterface.php | 18 + .../src/ServerRequestFactoryInterface.php | 24 + .../src/StreamFactoryInterface.php | 45 + .../src/UploadedFileFactoryInterface.php | 34 + .../http-factory/src/UriFactoryInterface.php | 17 + cacme/vendor/psr/http-message/CHANGELOG.md | 36 + cacme/vendor/psr/http-message/LICENSE | 19 + cacme/vendor/psr/http-message/README.md | 16 + cacme/vendor/psr/http-message/composer.json | 26 + .../psr/http-message/docs/PSR7-Interfaces.md | 130 + .../psr/http-message/docs/PSR7-Usage.md | 159 + .../psr/http-message/src/MessageInterface.php | 189 + .../psr/http-message/src/RequestInterface.php | 131 + .../http-message/src/ResponseInterface.php | 70 + .../src/ServerRequestInterface.php | 263 + .../psr/http-message/src/StreamInterface.php | 160 + .../src/UploadedFileInterface.php | 125 + .../psr/http-message/src/UriInterface.php | 326 + cacme/vendor/psr/log/LICENSE | 19 + cacme/vendor/psr/log/README.md | 58 + cacme/vendor/psr/log/composer.json | 26 + cacme/vendor/psr/log/src/AbstractLogger.php | 15 + .../psr/log/src/InvalidArgumentException.php | 7 + cacme/vendor/psr/log/src/LogLevel.php | 18 + .../psr/log/src/LoggerAwareInterface.php | 18 + cacme/vendor/psr/log/src/LoggerAwareTrait.php | 26 + cacme/vendor/psr/log/src/LoggerInterface.php | 125 + cacme/vendor/psr/log/src/LoggerTrait.php | 142 + cacme/vendor/psr/log/src/NullLogger.php | 30 + cacme/vendor/ralouphie/getallheaders/LICENSE | 21 + .../vendor/ralouphie/getallheaders/README.md | 27 + .../ralouphie/getallheaders/composer.json | 26 + .../getallheaders/src/getallheaders.php | 46 + cacme/vendor/respect/stringifier/LICENSE.md | 21 + cacme/vendor/respect/stringifier/README.md | 46 + .../vendor/respect/stringifier/composer.json | 36 + .../vendor/respect/stringifier/src/Quoter.php | 27 + .../stringifier/src/Quoters/CodeQuoter.php | 36 + .../respect/stringifier/src/Stringifier.php | 27 + .../src/Stringifiers/ArrayStringifier.php | 114 + .../src/Stringifiers/BoolStringifier.php | 53 + .../src/Stringifiers/ClusterStringifier.php | 117 + .../src/Stringifiers/DateTimeStringifier.php | 76 + .../src/Stringifiers/InfiniteStringifier.php | 58 + .../Stringifiers/JsonParsableStringifier.php | 40 + .../JsonSerializableStringifier.php | 67 + .../src/Stringifiers/NanStringifier.php | 58 + .../src/Stringifiers/NullStringifier.php | 52 + .../src/Stringifiers/ObjectStringifier.php | 70 + .../src/Stringifiers/ResourceStringifier.php | 61 + .../StringableObjectStringifier.php | 57 + .../src/Stringifiers/ThrowableStringifier.php | 84 + .../Stringifiers/TraversableStringifier.php | 69 + .../respect/stringifier/src/stringify.php | 27 + cacme/vendor/stella-maris/clock/.editorconfig | 15 + cacme/vendor/stella-maris/clock/LICENSE.md | 9 + cacme/vendor/stella-maris/clock/README.md | 66 + cacme/vendor/stella-maris/clock/composer.json | 27 + .../stella-maris/clock/src/ClockInterface.php | 15 + cacme/vendor/symfony/console/Application.php | 1267 ++ .../symfony/console/Attribute/AsCommand.php | 39 + cacme/vendor/symfony/console/CHANGELOG.md | 226 + .../console/CI/GithubActionReporter.php | 99 + cacme/vendor/symfony/console/Color.php | 180 + .../symfony/console/Command/Command.php | 676 + .../console/Command/CompleteCommand.php | 205 + .../console/Command/DumpCompletionCommand.php | 139 + .../symfony/console/Command/HelpCommand.php | 99 + .../symfony/console/Command/LazyCommand.php | 194 + .../symfony/console/Command/ListCommand.php | 95 + .../symfony/console/Command/LockableTrait.php | 67 + .../Command/SignalableCommandInterface.php | 30 + .../CommandLoader/CommandLoaderInterface.php | 38 + .../CommandLoader/ContainerCommandLoader.php | 64 + .../CommandLoader/FactoryCommandLoader.php | 63 + .../console/Completion/CompletionInput.php | 249 + .../Completion/CompletionSuggestions.php | 97 + .../Output/BashCompletionOutput.php | 33 + .../Output/CompletionOutputInterface.php | 25 + .../symfony/console/Completion/Suggestion.php | 37 + .../vendor/symfony/console/ConsoleEvents.php | 72 + cacme/vendor/symfony/console/Cursor.php | 207 + .../AddConsoleCommandPass.php | 131 + .../Descriptor/ApplicationDescription.php | 139 + .../symfony/console/Descriptor/Descriptor.php | 94 + .../Descriptor/DescriptorInterface.php | 24 + .../console/Descriptor/JsonDescriptor.php | 181 + .../console/Descriptor/MarkdownDescriptor.php | 206 + .../console/Descriptor/TextDescriptor.php | 339 + .../console/Descriptor/XmlDescriptor.php | 247 + .../console/Event/ConsoleCommandEvent.php | 51 + .../console/Event/ConsoleErrorEvent.php | 58 + .../symfony/console/Event/ConsoleEvent.php | 61 + .../console/Event/ConsoleSignalEvent.php | 35 + .../console/Event/ConsoleTerminateEvent.php | 43 + .../console/EventListener/ErrorListener.php | 95 + .../Exception/CommandNotFoundException.php | 43 + .../console/Exception/ExceptionInterface.php | 21 + .../Exception/InvalidArgumentException.php | 19 + .../Exception/InvalidOptionException.php | 21 + .../console/Exception/LogicException.php | 19 + .../Exception/MissingInputException.php | 21 + .../Exception/NamespaceNotFoundException.php | 21 + .../console/Exception/RuntimeException.php | 19 + .../console/Formatter/NullOutputFormatter.php | 69 + .../Formatter/NullOutputFormatterStyle.php | 66 + .../console/Formatter/OutputFormatter.php | 280 + .../Formatter/OutputFormatterInterface.php | 52 + .../Formatter/OutputFormatterStyle.php | 106 + .../OutputFormatterStyleInterface.php | 50 + .../Formatter/OutputFormatterStyleStack.php | 103 + .../WrappableOutputFormatterInterface.php | 25 + .../console/Helper/DebugFormatterHelper.php | 101 + .../console/Helper/DescriptorHelper.php | 92 + .../vendor/symfony/console/Helper/Dumper.php | 64 + .../console/Helper/FormatterHelper.php | 84 + .../vendor/symfony/console/Helper/Helper.php | 154 + .../console/Helper/HelperInterface.php | 37 + .../symfony/console/Helper/HelperSet.php | 74 + .../console/Helper/InputAwareHelper.php | 33 + .../symfony/console/Helper/ProcessHelper.php | 140 + .../symfony/console/Helper/ProgressBar.php | 603 + .../console/Helper/ProgressIndicator.php | 244 + .../symfony/console/Helper/QuestionHelper.php | 598 + .../console/Helper/SymfonyQuestionHelper.php | 109 + cacme/vendor/symfony/console/Helper/Table.php | 849 ++ .../symfony/console/Helper/TableCell.php | 72 + .../symfony/console/Helper/TableCellStyle.php | 86 + .../symfony/console/Helper/TableRows.php | 30 + .../symfony/console/Helper/TableSeparator.php | 25 + .../symfony/console/Helper/TableStyle.php | 362 + .../symfony/console/Input/ArgvInput.php | 376 + .../symfony/console/Input/ArrayInput.php | 205 + cacme/vendor/symfony/console/Input/Input.php | 211 + .../symfony/console/Input/InputArgument.php | 121 + .../console/Input/InputAwareInterface.php | 26 + .../symfony/console/Input/InputDefinition.php | 402 + .../symfony/console/Input/InputInterface.php | 137 + .../symfony/console/Input/InputOption.php | 218 + .../Input/StreamableInputInterface.php | 37 + .../symfony/console/Input/StringInput.php | 84 + cacme/vendor/symfony/console/LICENSE | 19 + .../symfony/console/Logger/ConsoleLogger.php | 122 + .../symfony/console/Output/BufferedOutput.php | 43 + .../symfony/console/Output/ConsoleOutput.php | 168 + .../console/Output/ConsoleOutputInterface.php | 30 + .../console/Output/ConsoleSectionOutput.php | 141 + .../symfony/console/Output/NullOutput.php | 125 + .../vendor/symfony/console/Output/Output.php | 174 + .../console/Output/OutputInterface.php | 94 + .../symfony/console/Output/StreamOutput.php | 115 + .../console/Output/TrimmedBufferOutput.php | 61 + .../console/Question/ChoiceQuestion.php | 177 + .../console/Question/ConfirmationQuestion.php | 57 + .../symfony/console/Question/Question.php | 283 + cacme/vendor/symfony/console/README.md | 36 + .../console/Resources/bin/hiddeninput.exe | Bin 0 -> 9216 bytes .../symfony/console/Resources/completion.bash | 84 + .../console/SignalRegistry/SignalRegistry.php | 65 + .../console/SingleCommandApplication.php | 72 + .../symfony/console/Style/OutputStyle.php | 150 + .../symfony/console/Style/StyleInterface.php | 110 + .../symfony/console/Style/SymfonyStyle.php | 500 + cacme/vendor/symfony/console/Terminal.php | 168 + .../console/Tester/ApplicationTester.php | 85 + .../Tester/CommandCompletionTester.php | 56 + .../symfony/console/Tester/CommandTester.php | 76 + .../Tester/Constraint/CommandIsSuccessful.php | 55 + .../symfony/console/Tester/TesterTrait.php | 180 + cacme/vendor/symfony/console/composer.json | 56 + .../symfony/deprecation-contracts/.gitignore | 3 + .../deprecation-contracts/CHANGELOG.md | 5 + .../symfony/deprecation-contracts/LICENSE | 19 + .../symfony/deprecation-contracts/README.md | 26 + .../deprecation-contracts/composer.json | 35 + .../deprecation-contracts/function.php | 27 + cacme/vendor/symfony/polyfill-ctype/Ctype.php | 232 + cacme/vendor/symfony/polyfill-ctype/LICENSE | 19 + cacme/vendor/symfony/polyfill-ctype/README.md | 12 + .../symfony/polyfill-ctype/bootstrap.php | 50 + .../symfony/polyfill-ctype/bootstrap80.php | 46 + .../symfony/polyfill-ctype/composer.json | 41 + .../polyfill-intl-grapheme/Grapheme.php | 247 + .../symfony/polyfill-intl-grapheme/LICENSE | 19 + .../symfony/polyfill-intl-grapheme/README.md | 31 + .../polyfill-intl-grapheme/bootstrap.php | 58 + .../polyfill-intl-grapheme/bootstrap80.php | 50 + .../polyfill-intl-grapheme/composer.json | 35 + .../symfony/polyfill-intl-normalizer/LICENSE | 19 + .../polyfill-intl-normalizer/Normalizer.php | 310 + .../polyfill-intl-normalizer/README.md | 14 + .../Resources/stubs/Normalizer.php | 17 + .../unidata/canonicalComposition.php | 945 ++ .../unidata/canonicalDecomposition.php | 2065 +++ .../Resources/unidata/combiningClass.php | 876 ++ .../unidata/compatibilityDecomposition.php | 3695 ++++++ .../polyfill-intl-normalizer/bootstrap.php | 23 + .../polyfill-intl-normalizer/bootstrap80.php | 19 + .../polyfill-intl-normalizer/composer.json | 39 + .../vendor/symfony/polyfill-mbstring/LICENSE | 19 + .../symfony/polyfill-mbstring/Mbstring.php | 947 ++ .../symfony/polyfill-mbstring/README.md | 13 + .../Resources/unidata/caseFolding.php | 119 + .../Resources/unidata/lowerCase.php | 1397 ++ .../Resources/unidata/titleCaseRegexp.php | 5 + .../Resources/unidata/upperCase.php | 1489 +++ .../symfony/polyfill-mbstring/bootstrap.php | 151 + .../symfony/polyfill-mbstring/bootstrap80.php | 147 + .../symfony/polyfill-mbstring/composer.json | 41 + .../symfony/service-contracts/.gitignore | 3 + .../service-contracts/Attribute/Required.php | 25 + .../Attribute/SubscribedService.php | 33 + .../symfony/service-contracts/CHANGELOG.md | 5 + .../vendor/symfony/service-contracts/LICENSE | 19 + .../symfony/service-contracts/README.md | 9 + .../service-contracts/ResetInterface.php | 30 + .../service-contracts/ServiceLocatorTrait.php | 124 + .../ServiceProviderInterface.php | 36 + .../ServiceSubscriberInterface.php | 53 + .../ServiceSubscriberTrait.php | 77 + .../Test/ServiceLocatorTest.php | 92 + .../symfony/service-contracts/composer.json | 41 + .../vendor/symfony/string/AbstractString.php | 716 ++ .../symfony/string/AbstractUnicodeString.php | 606 + cacme/vendor/symfony/string/ByteString.php | 493 + cacme/vendor/symfony/string/CHANGELOG.md | 35 + .../vendor/symfony/string/CodePointString.php | 260 + .../string/Exception/ExceptionInterface.php | 16 + .../Exception/InvalidArgumentException.php | 16 + .../string/Exception/RuntimeException.php | 16 + .../string/Inflector/EnglishInflector.php | 511 + .../string/Inflector/FrenchInflector.php | 157 + .../string/Inflector/InflectorInterface.php | 33 + cacme/vendor/symfony/string/LICENSE | 19 + cacme/vendor/symfony/string/LazyString.php | 143 + cacme/vendor/symfony/string/README.md | 14 + .../Resources/data/wcswidth_table_wide.php | 1143 ++ .../Resources/data/wcswidth_table_zero.php | 1415 ++ .../symfony/string/Resources/functions.php | 38 + .../symfony/string/Slugger/AsciiSlugger.php | 176 + .../string/Slugger/SluggerInterface.php | 27 + cacme/vendor/symfony/string/UnicodeString.php | 358 + cacme/vendor/symfony/string/composer.json | 42 + cacme/vendor/webman/console/.gitignore | 6 + cacme/vendor/webman/console/README.md | 3 + cacme/vendor/webman/console/composer.json | 37 + .../vendor/webman/console/src/Application.php | 115 + cacme/vendor/webman/console/src/Command.php | 54 + .../src/Commands/AppPluginCreateCommand.php | 472 + .../src/Commands/AppPluginInstallCommand.php | 44 + .../Commands/AppPluginUninstallCommand.php | 42 + .../console/src/Commands/BuildBinCommand.php | 149 + .../console/src/Commands/BuildPharCommand.php | 148 + .../src/Commands/ConnectionsCommand.php | 29 + .../Commands/FixDisbaleFunctionsCommand.php | 108 + .../console/src/Commands/InstallCommand.php | 40 + .../src/Commands/MakeBootstrapCommand.php | 117 + .../src/Commands/MakeCommandCommand.php | 116 + .../src/Commands/MakeControllerCommand.php | 103 + .../src/Commands/MakeMiddlewareCommand.php | 98 + .../console/src/Commands/MakeModelCommand.php | 299 + .../src/Commands/PluginCreateCommand.php | 213 + .../src/Commands/PluginDisableCommand.php | 51 + .../src/Commands/PluginEnableCommand.php | 56 + .../src/Commands/PluginExportCommand.php | 152 + .../src/Commands/PluginInstallCommand.php | 43 + .../src/Commands/PluginUninstallCommand.php | 47 + .../console/src/Commands/ReStartCommand.php | 37 + .../console/src/Commands/ReloadCommand.php | 36 + .../console/src/Commands/RouteListCommand.php | 39 + .../console/src/Commands/StartCommand.php | 35 + .../console/src/Commands/StatusCommand.php | 35 + .../console/src/Commands/StopCommand.php | 34 + .../console/src/Commands/VersionCommand.php | 29 + cacme/vendor/webman/console/src/Install.php | 76 + cacme/vendor/webman/console/src/Util.php | 66 + .../src/config/plugin/webman/console/app.php | 24 + cacme/vendor/webman/console/src/webman | 57 + cacme/vendor/webmozart/assert/CHANGELOG.md | 207 + cacme/vendor/webmozart/assert/LICENSE | 20 + cacme/vendor/webmozart/assert/README.md | 287 + cacme/vendor/webmozart/assert/composer.json | 43 + cacme/vendor/webmozart/assert/src/Assert.php | 2080 +++ .../assert/src/InvalidArgumentException.php | 16 + cacme/vendor/webmozart/assert/src/Mixin.php | 5089 ++++++++ .../vendor/workerman/validation/CHANGELOG.md | 161 + .../workerman/validation/CONTRIBUTING.md | 244 + cacme/vendor/workerman/validation/LICENSE | 21 + cacme/vendor/workerman/validation/README.md | 20 + .../vendor/workerman/validation/composer.json | 73 + .../data/domain/public-suffix/AC.php | 11 + .../data/domain/public-suffix/AD.php | 6 + .../data/domain/public-suffix/AE.php | 12 + .../data/domain/public-suffix/AERO.php | 91 + .../data/domain/public-suffix/AF.php | 10 + .../data/domain/public-suffix/AG.php | 10 + .../data/domain/public-suffix/AI.php | 9 + .../data/domain/public-suffix/AL.php | 11 + .../data/domain/public-suffix/AM.php | 10 + .../data/domain/public-suffix/AO.php | 11 + .../data/domain/public-suffix/AR.php | 19 + .../data/domain/public-suffix/ARPA.php | 11 + .../data/domain/public-suffix/AS.php | 6 + .../data/domain/public-suffix/AT.php | 10 + .../data/domain/public-suffix/AU.php | 38 + .../data/domain/public-suffix/AW.php | 6 + .../data/domain/public-suffix/AZ.php | 17 + .../data/domain/public-suffix/BA.php | 11 + .../data/domain/public-suffix/BB.php | 15 + .../data/domain/public-suffix/BE.php | 6 + .../data/domain/public-suffix/BF.php | 6 + .../data/domain/public-suffix/BG.php | 41 + .../data/domain/public-suffix/BH.php | 10 + .../data/domain/public-suffix/BI.php | 10 + .../data/domain/public-suffix/BJ.php | 25 + .../data/domain/public-suffix/BM.php | 10 + .../data/domain/public-suffix/BN.php | 10 + .../data/domain/public-suffix/BO.php | 46 + .../data/domain/public-suffix/BR.php | 173 + .../data/domain/public-suffix/BS.php | 10 + .../data/domain/public-suffix/BT.php | 10 + .../data/domain/public-suffix/BW.php | 7 + .../data/domain/public-suffix/BY.php | 9 + .../data/domain/public-suffix/BZ.php | 10 + .../data/domain/public-suffix/CA.php | 20 + .../data/domain/public-suffix/CD.php | 6 + .../data/domain/public-suffix/CI.php | 20 + .../data/domain/public-suffix/CK.php | 6 + .../data/domain/public-suffix/CL.php | 9 + .../data/domain/public-suffix/CM.php | 9 + .../data/domain/public-suffix/CN.php | 49 + .../data/domain/public-suffix/CO.php | 18 + .../data/domain/public-suffix/CR.php | 12 + .../data/domain/public-suffix/CU.php | 11 + .../data/domain/public-suffix/CV.php | 10 + .../data/domain/public-suffix/CW.php | 9 + .../data/domain/public-suffix/CX.php | 6 + .../data/domain/public-suffix/CY.php | 17 + .../data/domain/public-suffix/DM.php | 10 + .../data/domain/public-suffix/DO.php | 15 + .../data/domain/public-suffix/DZ.php | 15 + .../data/domain/public-suffix/EC.php | 17 + .../data/domain/public-suffix/EE.php | 15 + .../data/domain/public-suffix/EG.php | 14 + .../data/domain/public-suffix/ES.php | 10 + .../data/domain/public-suffix/ET.php | 13 + .../data/domain/public-suffix/FI.php | 6 + .../data/domain/public-suffix/FJ.php | 15 + .../data/domain/public-suffix/FM.php | 9 + .../data/domain/public-suffix/FR.php | 26 + .../data/domain/public-suffix/GD.php | 7 + .../data/domain/public-suffix/GE.php | 12 + .../data/domain/public-suffix/GG.php | 8 + .../data/domain/public-suffix/GH.php | 10 + .../data/domain/public-suffix/GI.php | 11 + .../data/domain/public-suffix/GL.php | 10 + .../data/domain/public-suffix/GN.php | 11 + .../data/domain/public-suffix/GP.php | 11 + .../data/domain/public-suffix/GR.php | 10 + .../data/domain/public-suffix/GT.php | 12 + .../data/domain/public-suffix/GU.php | 13 + .../data/domain/public-suffix/GY.php | 11 + .../data/domain/public-suffix/HK.php | 26 + .../data/domain/public-suffix/HN.php | 11 + .../data/domain/public-suffix/HR.php | 9 + .../data/domain/public-suffix/HT.php | 22 + .../data/domain/public-suffix/HU.php | 36 + .../data/domain/public-suffix/ID.php | 17 + .../data/domain/public-suffix/IE.php | 6 + .../data/domain/public-suffix/IL.php | 13 + .../data/domain/public-suffix/IM.php | 14 + .../data/domain/public-suffix/IN.php | 46 + .../data/domain/public-suffix/INT.php | 6 + .../data/domain/public-suffix/IO.php | 6 + .../data/domain/public-suffix/IQ.php | 11 + .../data/domain/public-suffix/IR.php | 14 + .../data/domain/public-suffix/IS.php | 11 + .../data/domain/public-suffix/IT.php | 411 + .../data/domain/public-suffix/JE.php | 8 + .../data/domain/public-suffix/JO.php | 13 + .../data/domain/public-suffix/JP.php | 1795 +++ .../data/domain/public-suffix/KE.php | 14 + .../data/domain/public-suffix/KG.php | 11 + .../data/domain/public-suffix/KI.php | 12 + .../data/domain/public-suffix/KM.php | 22 + .../data/domain/public-suffix/KN.php | 9 + .../data/domain/public-suffix/KP.php | 11 + .../data/domain/public-suffix/KR.php | 34 + .../data/domain/public-suffix/KW.php | 12 + .../data/domain/public-suffix/KY.php | 9 + .../data/domain/public-suffix/KZ.php | 11 + .../data/domain/public-suffix/LA.php | 13 + .../data/domain/public-suffix/LB.php | 10 + .../data/domain/public-suffix/LC.php | 11 + .../data/domain/public-suffix/LK.php | 20 + .../data/domain/public-suffix/LR.php | 10 + .../data/domain/public-suffix/LS.php | 14 + .../data/domain/public-suffix/LT.php | 6 + .../data/domain/public-suffix/LV.php | 14 + .../data/domain/public-suffix/LY.php | 14 + .../data/domain/public-suffix/MA.php | 11 + .../data/domain/public-suffix/MC.php | 7 + .../data/domain/public-suffix/ME.php | 13 + .../data/domain/public-suffix/MG.php | 14 + .../data/domain/public-suffix/MK.php | 12 + .../data/domain/public-suffix/ML.php | 12 + .../data/domain/public-suffix/MN.php | 8 + .../data/domain/public-suffix/MO.php | 10 + .../data/domain/public-suffix/MR.php | 6 + .../data/domain/public-suffix/MS.php | 10 + .../data/domain/public-suffix/MT.php | 9 + .../data/domain/public-suffix/MU.php | 12 + .../data/domain/public-suffix/MV.php | 19 + .../data/domain/public-suffix/MW.php | 16 + .../data/domain/public-suffix/MX.php | 10 + .../data/domain/public-suffix/MY.php | 13 + .../data/domain/public-suffix/MZ.php | 13 + .../data/domain/public-suffix/NA.php | 22 + .../data/domain/public-suffix/NC.php | 7 + .../data/domain/public-suffix/NF.php | 15 + .../data/domain/public-suffix/NG.php | 15 + .../data/domain/public-suffix/NI.php | 19 + .../data/domain/public-suffix/NO.php | 758 ++ .../data/domain/public-suffix/NR.php | 12 + .../data/domain/public-suffix/NZ.php | 21 + .../data/domain/public-suffix/OM.php | 14 + .../data/domain/public-suffix/PA.php | 16 + .../data/domain/public-suffix/PE.php | 12 + .../data/domain/public-suffix/PF.php | 8 + .../data/domain/public-suffix/PH.php | 13 + .../data/domain/public-suffix/PK.php | 19 + .../data/domain/public-suffix/PL.php | 213 + .../data/domain/public-suffix/PN.php | 10 + .../data/domain/public-suffix/PR.php | 18 + .../data/domain/public-suffix/PRO.php | 16 + .../data/domain/public-suffix/PS.php | 12 + .../data/domain/public-suffix/PT.php | 13 + .../data/domain/public-suffix/PW.php | 11 + .../data/domain/public-suffix/PY.php | 12 + .../data/domain/public-suffix/QA.php | 13 + .../data/domain/public-suffix/RE.php | 8 + .../data/domain/public-suffix/RO.php | 16 + .../data/domain/public-suffix/RS.php | 11 + .../data/domain/public-suffix/RW.php | 12 + .../data/domain/public-suffix/SA.php | 13 + .../data/domain/public-suffix/SB.php | 10 + .../data/domain/public-suffix/SC.php | 10 + .../data/domain/public-suffix/SD.php | 13 + .../data/domain/public-suffix/SE.php | 44 + .../data/domain/public-suffix/SG.php | 11 + .../data/domain/public-suffix/SH.php | 10 + .../data/domain/public-suffix/SL.php | 10 + .../data/domain/public-suffix/SN.php | 12 + .../data/domain/public-suffix/SO.php | 11 + .../data/domain/public-suffix/SS.php | 13 + .../data/domain/public-suffix/ST.php | 16 + .../data/domain/public-suffix/SV.php | 10 + .../data/domain/public-suffix/SX.php | 6 + .../data/domain/public-suffix/SY.php | 11 + .../data/domain/public-suffix/SZ.php | 8 + .../data/domain/public-suffix/TH.php | 12 + .../data/domain/public-suffix/TJ.php | 20 + .../data/domain/public-suffix/TL.php | 6 + .../data/domain/public-suffix/TM.php | 13 + .../data/domain/public-suffix/TN.php | 18 + .../data/domain/public-suffix/TO.php | 11 + .../data/domain/public-suffix/TR.php | 28 + .../data/domain/public-suffix/TT.php | 22 + .../data/domain/public-suffix/TW.php | 18 + .../data/domain/public-suffix/TZ.php | 17 + .../data/domain/public-suffix/UA.php | 81 + .../data/domain/public-suffix/UG.php | 13 + .../data/domain/public-suffix/UK.php | 16 + .../data/domain/public-suffix/US.php | 234 + .../data/domain/public-suffix/UY.php | 11 + .../data/domain/public-suffix/UZ.php | 9 + .../data/domain/public-suffix/VC.php | 11 + .../data/domain/public-suffix/VE.php | 25 + .../data/domain/public-suffix/VI.php | 10 + .../data/domain/public-suffix/VN.php | 17 + .../data/domain/public-suffix/VU.php | 9 + .../data/domain/public-suffix/WS.php | 10 + .../domain/public-suffix/XN--4DBRK0CE.php | 9 + .../data/domain/public-suffix/XN--90A3AC.php | 11 + .../data/domain/public-suffix/XN--J6W193G.php | 11 + .../data/domain/public-suffix/XN--O3CW4H.php | 11 + .../data/domain/public-suffix/YE.php | 11 + .../data/domain/public-suffix/ZA.php | 23 + .../data/domain/public-suffix/ZM.php | 16 + .../data/domain/public-suffix/ZW.php | 10 + .../validation/data/iso_3166-2/AD.php | 13 + .../validation/data/iso_3166-2/AE.php | 13 + .../validation/data/iso_3166-2/AF.php | 40 + .../validation/data/iso_3166-2/AG.php | 14 + .../validation/data/iso_3166-2/AI.php | 6 + .../validation/data/iso_3166-2/AL.php | 18 + .../validation/data/iso_3166-2/AM.php | 17 + .../validation/data/iso_3166-2/AO.php | 24 + .../validation/data/iso_3166-2/AQ.php | 6 + .../validation/data/iso_3166-2/AR.php | 30 + .../validation/data/iso_3166-2/AS.php | 6 + .../validation/data/iso_3166-2/AT.php | 15 + .../validation/data/iso_3166-2/AU.php | 14 + .../validation/data/iso_3166-2/AW.php | 6 + .../validation/data/iso_3166-2/AX.php | 6 + .../validation/data/iso_3166-2/AZ.php | 84 + .../validation/data/iso_3166-2/BA.php | 9 + .../validation/data/iso_3166-2/BB.php | 17 + .../validation/data/iso_3166-2/BD.php | 78 + .../validation/data/iso_3166-2/BE.php | 19 + .../validation/data/iso_3166-2/BF.php | 64 + .../validation/data/iso_3166-2/BG.php | 34 + .../validation/data/iso_3166-2/BH.php | 10 + .../validation/data/iso_3166-2/BI.php | 24 + .../validation/data/iso_3166-2/BJ.php | 18 + .../validation/data/iso_3166-2/BL.php | 6 + .../validation/data/iso_3166-2/BM.php | 6 + .../validation/data/iso_3166-2/BN.php | 10 + .../validation/data/iso_3166-2/BO.php | 15 + .../validation/data/iso_3166-2/BQ.php | 9 + .../validation/data/iso_3166-2/BR.php | 33 + .../validation/data/iso_3166-2/BS.php | 38 + .../validation/data/iso_3166-2/BT.php | 26 + .../validation/data/iso_3166-2/BV.php | 6 + .../validation/data/iso_3166-2/BW.php | 22 + .../validation/data/iso_3166-2/BY.php | 13 + .../validation/data/iso_3166-2/BZ.php | 12 + .../validation/data/iso_3166-2/CA.php | 19 + .../validation/data/iso_3166-2/CC.php | 6 + .../validation/data/iso_3166-2/CD.php | 32 + .../validation/data/iso_3166-2/CF.php | 23 + .../validation/data/iso_3166-2/CG.php | 18 + .../validation/data/iso_3166-2/CH.php | 32 + .../validation/data/iso_3166-2/CI.php | 20 + .../validation/data/iso_3166-2/CK.php | 6 + .../validation/data/iso_3166-2/CL.php | 22 + .../validation/data/iso_3166-2/CM.php | 16 + .../validation/data/iso_3166-2/CN.php | 40 + .../validation/data/iso_3166-2/CO.php | 39 + .../validation/data/iso_3166-2/CR.php | 13 + .../validation/data/iso_3166-2/CU.php | 22 + .../validation/data/iso_3166-2/CV.php | 30 + .../validation/data/iso_3166-2/CW.php | 6 + .../validation/data/iso_3166-2/CX.php | 6 + .../validation/data/iso_3166-2/CY.php | 12 + .../validation/data/iso_3166-2/CZ.php | 96 + .../validation/data/iso_3166-2/DE.php | 22 + .../validation/data/iso_3166-2/DJ.php | 12 + .../validation/data/iso_3166-2/DK.php | 11 + .../validation/data/iso_3166-2/DM.php | 16 + .../validation/data/iso_3166-2/DO.php | 48 + .../validation/data/iso_3166-2/DZ.php | 54 + .../validation/data/iso_3166-2/EC.php | 30 + .../validation/data/iso_3166-2/EE.php | 100 + .../validation/data/iso_3166-2/EG.php | 33 + .../validation/data/iso_3166-2/EH.php | 6 + .../validation/data/iso_3166-2/ER.php | 12 + .../validation/data/iso_3166-2/ES.php | 75 + .../validation/data/iso_3166-2/ET.php | 17 + .../validation/data/iso_3166-2/FI.php | 25 + .../validation/data/iso_3166-2/FJ.php | 25 + .../validation/data/iso_3166-2/FK.php | 6 + .../validation/data/iso_3166-2/FM.php | 10 + .../validation/data/iso_3166-2/FO.php | 6 + .../validation/data/iso_3166-2/FR.php | 133 + .../validation/data/iso_3166-2/GA.php | 15 + .../validation/data/iso_3166-2/GB.php | 226 + .../validation/data/iso_3166-2/GD.php | 13 + .../validation/data/iso_3166-2/GE.php | 18 + .../validation/data/iso_3166-2/GF.php | 6 + .../validation/data/iso_3166-2/GG.php | 6 + .../validation/data/iso_3166-2/GH.php | 22 + .../validation/data/iso_3166-2/GI.php | 6 + .../validation/data/iso_3166-2/GL.php | 11 + .../validation/data/iso_3166-2/GM.php | 12 + .../validation/data/iso_3166-2/GN.php | 47 + .../validation/data/iso_3166-2/GP.php | 6 + .../validation/data/iso_3166-2/GQ.php | 16 + .../validation/data/iso_3166-2/GR.php | 20 + .../validation/data/iso_3166-2/GS.php | 6 + .../validation/data/iso_3166-2/GT.php | 28 + .../validation/data/iso_3166-2/GU.php | 6 + .../validation/data/iso_3166-2/GW.php | 18 + .../validation/data/iso_3166-2/GY.php | 16 + .../validation/data/iso_3166-2/HK.php | 6 + .../validation/data/iso_3166-2/HM.php | 6 + .../validation/data/iso_3166-2/HN.php | 24 + .../validation/data/iso_3166-2/HR.php | 27 + .../validation/data/iso_3166-2/HT.php | 16 + .../validation/data/iso_3166-2/HU.php | 49 + .../validation/data/iso_3166-2/ID.php | 47 + .../validation/data/iso_3166-2/IE.php | 36 + .../validation/data/iso_3166-2/IL.php | 12 + .../validation/data/iso_3166-2/IM.php | 6 + .../validation/data/iso_3166-2/IN.php | 42 + .../validation/data/iso_3166-2/IO.php | 6 + .../validation/data/iso_3166-2/IQ.php | 24 + .../validation/data/iso_3166-2/IR.php | 37 + .../validation/data/iso_3166-2/IS.php | 86 + .../validation/data/iso_3166-2/IT.php | 132 + .../validation/data/iso_3166-2/JE.php | 6 + .../validation/data/iso_3166-2/JM.php | 20 + .../validation/data/iso_3166-2/JO.php | 18 + .../validation/data/iso_3166-2/JP.php | 53 + .../validation/data/iso_3166-2/KE.php | 53 + .../validation/data/iso_3166-2/KG.php | 15 + .../validation/data/iso_3166-2/KH.php | 31 + .../validation/data/iso_3166-2/KI.php | 9 + .../validation/data/iso_3166-2/KM.php | 9 + .../validation/data/iso_3166-2/KN.php | 22 + .../validation/data/iso_3166-2/KP.php | 18 + .../validation/data/iso_3166-2/KR.php | 23 + .../validation/data/iso_3166-2/KW.php | 12 + .../validation/data/iso_3166-2/KY.php | 6 + .../validation/data/iso_3166-2/KZ.php | 23 + .../validation/data/iso_3166-2/LA.php | 24 + .../validation/data/iso_3166-2/LB.php | 14 + .../validation/data/iso_3166-2/LC.php | 16 + .../validation/data/iso_3166-2/LI.php | 17 + .../validation/data/iso_3166-2/LK.php | 40 + .../validation/data/iso_3166-2/LR.php | 21 + .../validation/data/iso_3166-2/LS.php | 16 + .../validation/data/iso_3166-2/LT.php | 76 + .../validation/data/iso_3166-2/LU.php | 18 + .../validation/data/iso_3166-2/LV.php | 125 + .../validation/data/iso_3166-2/LY.php | 28 + .../validation/data/iso_3166-2/MA.php | 93 + .../validation/data/iso_3166-2/MC.php | 23 + .../validation/data/iso_3166-2/MD.php | 43 + .../validation/data/iso_3166-2/ME.php | 30 + .../validation/data/iso_3166-2/MF.php | 6 + .../validation/data/iso_3166-2/MG.php | 12 + .../validation/data/iso_3166-2/MH.php | 32 + .../validation/data/iso_3166-2/MK.php | 86 + .../validation/data/iso_3166-2/ML.php | 17 + .../validation/data/iso_3166-2/MM.php | 21 + .../validation/data/iso_3166-2/MN.php | 28 + .../validation/data/iso_3166-2/MO.php | 6 + .../validation/data/iso_3166-2/MP.php | 6 + .../validation/data/iso_3166-2/MQ.php | 6 + .../validation/data/iso_3166-2/MR.php | 21 + .../validation/data/iso_3166-2/MS.php | 6 + .../validation/data/iso_3166-2/MT.php | 74 + .../validation/data/iso_3166-2/MU.php | 18 + .../validation/data/iso_3166-2/MV.php | 27 + .../validation/data/iso_3166-2/MW.php | 37 + .../validation/data/iso_3166-2/MX.php | 38 + .../validation/data/iso_3166-2/MY.php | 22 + .../validation/data/iso_3166-2/MZ.php | 17 + .../validation/data/iso_3166-2/NA.php | 20 + .../validation/data/iso_3166-2/NC.php | 6 + .../validation/data/iso_3166-2/NE.php | 14 + .../validation/data/iso_3166-2/NF.php | 6 + .../validation/data/iso_3166-2/NG.php | 43 + .../validation/data/iso_3166-2/NI.php | 23 + .../validation/data/iso_3166-2/NL.php | 24 + .../validation/data/iso_3166-2/NO.php | 19 + .../validation/data/iso_3166-2/NP.php | 32 + .../validation/data/iso_3166-2/NR.php | 20 + .../validation/data/iso_3166-2/NU.php | 6 + .../validation/data/iso_3166-2/NZ.php | 23 + .../validation/data/iso_3166-2/OM.php | 17 + .../validation/data/iso_3166-2/PA.php | 19 + .../validation/data/iso_3166-2/PE.php | 32 + .../validation/data/iso_3166-2/PF.php | 6 + .../validation/data/iso_3166-2/PG.php | 28 + .../validation/data/iso_3166-2/PH.php | 104 + .../validation/data/iso_3166-2/PK.php | 13 + .../validation/data/iso_3166-2/PL.php | 22 + .../validation/data/iso_3166-2/PM.php | 6 + .../validation/data/iso_3166-2/PN.php | 6 + .../validation/data/iso_3166-2/PR.php | 6 + .../validation/data/iso_3166-2/PS.php | 22 + .../validation/data/iso_3166-2/PT.php | 26 + .../validation/data/iso_3166-2/PW.php | 22 + .../validation/data/iso_3166-2/PY.php | 24 + .../validation/data/iso_3166-2/QA.php | 14 + .../validation/data/iso_3166-2/RE.php | 6 + .../validation/data/iso_3166-2/RO.php | 48 + .../validation/data/iso_3166-2/RS.php | 38 + .../validation/data/iso_3166-2/RU.php | 89 + .../validation/data/iso_3166-2/RW.php | 11 + .../validation/data/iso_3166-2/SA.php | 19 + .../validation/data/iso_3166-2/SB.php | 16 + .../validation/data/iso_3166-2/SC.php | 33 + .../validation/data/iso_3166-2/SD.php | 24 + .../validation/data/iso_3166-2/SE.php | 27 + .../validation/data/iso_3166-2/SG.php | 11 + .../validation/data/iso_3166-2/SH.php | 9 + .../validation/data/iso_3166-2/SI.php | 218 + .../validation/data/iso_3166-2/SJ.php | 6 + .../validation/data/iso_3166-2/SK.php | 14 + .../validation/data/iso_3166-2/SL.php | 11 + .../validation/data/iso_3166-2/SM.php | 15 + .../validation/data/iso_3166-2/SN.php | 20 + .../validation/data/iso_3166-2/SO.php | 24 + .../validation/data/iso_3166-2/SR.php | 16 + .../validation/data/iso_3166-2/SS.php | 16 + .../validation/data/iso_3166-2/ST.php | 13 + .../validation/data/iso_3166-2/SV.php | 20 + .../validation/data/iso_3166-2/SX.php | 6 + .../validation/data/iso_3166-2/SY.php | 20 + .../validation/data/iso_3166-2/SZ.php | 10 + .../validation/data/iso_3166-2/TC.php | 6 + .../validation/data/iso_3166-2/TD.php | 29 + .../validation/data/iso_3166-2/TF.php | 6 + .../validation/data/iso_3166-2/TG.php | 11 + .../validation/data/iso_3166-2/TH.php | 84 + .../validation/data/iso_3166-2/TJ.php | 11 + .../validation/data/iso_3166-2/TK.php | 6 + .../validation/data/iso_3166-2/TL.php | 19 + .../validation/data/iso_3166-2/TM.php | 12 + .../validation/data/iso_3166-2/TN.php | 30 + .../validation/data/iso_3166-2/TO.php | 11 + .../validation/data/iso_3166-2/TR.php | 87 + .../validation/data/iso_3166-2/TT.php | 21 + .../validation/data/iso_3166-2/TV.php | 14 + .../validation/data/iso_3166-2/TW.php | 28 + .../validation/data/iso_3166-2/TZ.php | 37 + .../validation/data/iso_3166-2/UA.php | 33 + .../validation/data/iso_3166-2/UG.php | 145 + .../validation/data/iso_3166-2/UM.php | 15 + .../validation/data/iso_3166-2/US.php | 63 + .../validation/data/iso_3166-2/UY.php | 25 + .../validation/data/iso_3166-2/UZ.php | 20 + .../validation/data/iso_3166-2/VA.php | 6 + .../validation/data/iso_3166-2/VC.php | 12 + .../validation/data/iso_3166-2/VE.php | 31 + .../validation/data/iso_3166-2/VG.php | 6 + .../validation/data/iso_3166-2/VI.php | 6 + .../validation/data/iso_3166-2/VN.php | 69 + .../validation/data/iso_3166-2/VU.php | 12 + .../validation/data/iso_3166-2/WF.php | 9 + .../validation/data/iso_3166-2/WS.php | 17 + .../validation/data/iso_3166-2/YE.php | 28 + .../validation/data/iso_3166-2/YT.php | 6 + .../validation/data/iso_3166-2/ZA.php | 15 + .../validation/data/iso_3166-2/ZM.php | 16 + .../validation/data/iso_3166-2/ZW.php | 16 + .../validation/library/ChainedValidator.php | 377 + .../library/Exceptions/AllOfException.php | 31 + .../library/Exceptions/AlnumException.php | 31 + .../library/Exceptions/AlphaException.php | 31 + .../Exceptions/AlwaysInvalidException.php | 34 + .../Exceptions/AlwaysValidException.php | 30 + .../library/Exceptions/AnyOfException.php | 29 + .../library/Exceptions/ArrayTypeException.php | 31 + .../library/Exceptions/ArrayValException.php | 30 + .../library/Exceptions/AttributeException.php | 45 + .../library/Exceptions/Base64Exception.php | 30 + .../library/Exceptions/BaseException.php | 30 + .../library/Exceptions/BetweenException.php | 29 + .../library/Exceptions/BoolTypeException.php | 31 + .../library/Exceptions/BoolValException.php | 30 + .../library/Exceptions/BsnException.php | 30 + .../library/Exceptions/CallException.php | 29 + .../Exceptions/CallableTypeException.php | 30 + .../library/Exceptions/CallbackException.php | 19 + .../library/Exceptions/CharsetException.php | 30 + .../library/Exceptions/CnhException.php | 30 + .../library/Exceptions/CnpjException.php | 30 + .../library/Exceptions/ComponentException.php | 21 + .../library/Exceptions/ConsonantException.php | 32 + .../Exceptions/ContainsAnyException.php | 28 + .../library/Exceptions/ContainsException.php | 30 + .../library/Exceptions/ControlException.php | 32 + .../library/Exceptions/CountableException.php | 30 + .../Exceptions/CountryCodeException.php | 30 + .../library/Exceptions/CpfException.php | 30 + .../Exceptions/CreditCardException.php | 48 + .../Exceptions/CurrencyCodeException.php | 30 + .../library/Exceptions/DateException.php | 29 + .../library/Exceptions/DateTimeException.php | 41 + .../library/Exceptions/DecimalException.php | 28 + .../library/Exceptions/DigitException.php | 31 + .../library/Exceptions/DirectoryException.php | 29 + .../library/Exceptions/DomainException.php | 29 + .../library/Exceptions/EachException.php | 52 + .../library/Exceptions/EmailException.php | 34 + .../library/Exceptions/EndsWithException.php | 30 + .../library/Exceptions/EqualsException.php | 30 + .../Exceptions/EquivalentException.php | 28 + .../library/Exceptions/EvenException.php | 32 + .../library/Exceptions/Exception.php | 20 + .../Exceptions/ExecutableException.php | 29 + .../library/Exceptions/ExistsException.php | 29 + .../library/Exceptions/ExtensionException.php | 31 + .../library/Exceptions/FactorException.php | 30 + .../library/Exceptions/FalseValException.php | 29 + .../library/Exceptions/FibonacciException.php | 30 + .../library/Exceptions/FileException.php | 29 + .../library/Exceptions/FilterVarException.php | 17 + .../FilteredValidationException.php | 26 + .../library/Exceptions/FiniteException.php | 29 + .../library/Exceptions/FloatTypeException.php | 31 + .../library/Exceptions/FloatValException.php | 30 + .../library/Exceptions/GraphException.php | 32 + .../Exceptions/GreaterThanException.php | 28 + .../Exceptions/GroupedValidationException.php | 47 + .../Exceptions/HexRgbColorException.php | 29 + .../library/Exceptions/IbanException.php | 28 + .../library/Exceptions/IdenticalException.php | 28 + .../library/Exceptions/ImageException.php | 30 + .../library/Exceptions/ImeiException.php | 30 + .../library/Exceptions/InException.php | 30 + .../library/Exceptions/InfiniteException.php | 29 + .../library/Exceptions/InstanceException.php | 30 + .../library/Exceptions/IntTypeException.php | 30 + .../library/Exceptions/IntValException.php | 30 + .../Exceptions/InvalidClassException.php | 21 + .../library/Exceptions/IpException.php | 47 + .../library/Exceptions/IsbnException.php | 29 + .../Exceptions/IterableTypeException.php | 28 + .../library/Exceptions/JsonException.php | 30 + .../library/Exceptions/KeyException.php | 45 + .../library/Exceptions/KeyNestedException.php | 45 + .../library/Exceptions/KeySetException.php | 50 + .../library/Exceptions/KeyValueException.php | 37 + .../Exceptions/LanguageCodeException.php | 30 + .../library/Exceptions/LeapDateException.php | 29 + .../library/Exceptions/LeapYearException.php | 29 + .../library/Exceptions/LengthException.php | 70 + .../library/Exceptions/LessThanException.php | 28 + .../library/Exceptions/LowercaseException.php | 30 + .../library/Exceptions/LuhnException.php | 30 + .../Exceptions/MacAddressException.php | 30 + .../library/Exceptions/MaxAgeException.php | 29 + .../library/Exceptions/MaxException.php | 30 + .../library/Exceptions/MimetypeException.php | 31 + .../library/Exceptions/MinAgeException.php | 30 + .../library/Exceptions/MinException.php | 31 + .../library/Exceptions/MultipleException.php | 30 + .../library/Exceptions/NegativeException.php | 30 + .../Exceptions/NestedValidationException.php | 255 + .../Exceptions/NfeAccessKeyException.php | 30 + .../library/Exceptions/NifException.php | 29 + .../library/Exceptions/NipException.php | 29 + .../library/Exceptions/NoException.php | 28 + .../Exceptions/NoWhitespaceException.php | 30 + .../Exceptions/NonOmissibleException.php | 18 + .../library/Exceptions/NoneOfException.php | 29 + .../library/Exceptions/NotBlankException.php | 45 + .../library/Exceptions/NotEmojiException.php | 28 + .../library/Exceptions/NotEmptyException.php | 46 + .../library/Exceptions/NotException.php | 18 + .../Exceptions/NotOptionalException.php | 45 + .../library/Exceptions/NullTypeException.php | 31 + .../library/Exceptions/NullableException.php | 45 + .../library/Exceptions/NumberException.php | 30 + .../Exceptions/NumericValException.php | 30 + .../Exceptions/ObjectTypeException.php | 31 + .../library/Exceptions/OddException.php | 30 + .../library/Exceptions/OneOfException.php | 29 + .../library/Exceptions/OptionalException.php | 37 + .../Exceptions/PerfectSquareException.php | 30 + .../library/Exceptions/PeselException.php | 30 + .../library/Exceptions/PhoneException.php | 55 + .../library/Exceptions/PhpLabelException.php | 30 + .../library/Exceptions/PisException.php | 30 + .../Exceptions/PolishIdCardException.php | 28 + .../Exceptions/PortugueseNifException.php | 28 + .../library/Exceptions/PositiveException.php | 30 + .../Exceptions/PostalCodeException.php | 28 + .../Exceptions/PrimeNumberException.php | 30 + .../library/Exceptions/PrintableException.php | 35 + .../PublicDomainSuffixException.php | 28 + .../library/Exceptions/PunctException.php | 32 + .../library/Exceptions/ReadableException.php | 29 + .../Exceptions/RecursiveExceptionIterator.php | 85 + .../library/Exceptions/RegexException.php | 30 + .../Exceptions/ResourceTypeException.php | 30 + .../library/Exceptions/RomanException.php | 29 + .../library/Exceptions/ScalarValException.php | 28 + .../library/Exceptions/SfException.php | 33 + .../library/Exceptions/SizeException.php | 54 + .../library/Exceptions/SlugException.php | 30 + .../library/Exceptions/SortedException.php | 44 + .../library/Exceptions/SpaceException.php | 31 + .../Exceptions/StartsWithException.php | 29 + .../Exceptions/StringTypeException.php | 29 + .../library/Exceptions/StringValException.php | 29 + .../Exceptions/SubdivisionCodeException.php | 28 + .../library/Exceptions/SubsetException.php | 29 + .../Exceptions/SymbolicLinkException.php | 29 + .../library/Exceptions/TimeException.php | 28 + .../library/Exceptions/TldException.php | 33 + .../library/Exceptions/TrueValException.php | 31 + .../library/Exceptions/TypeException.php | 31 + .../library/Exceptions/UniqueException.php | 32 + .../library/Exceptions/UploadedException.php | 32 + .../library/Exceptions/UppercaseException.php | 30 + .../library/Exceptions/UrlException.php | 28 + .../library/Exceptions/UuidException.php | 46 + .../Exceptions/ValidationException.php | 158 + .../library/Exceptions/ValidatorException.php | 17 + .../library/Exceptions/VersionException.php | 29 + .../library/Exceptions/VideoUrlException.php | 46 + .../library/Exceptions/VowelException.php | 31 + .../library/Exceptions/WhenException.php | 19 + .../library/Exceptions/WritableException.php | 29 + .../library/Exceptions/XdigitException.php | 31 + .../library/Exceptions/YesException.php | 29 + .../workerman/validation/library/Factory.php | 266 + .../library/Helpers/CanCompareValues.php | 68 + .../library/Helpers/CanValidateDateTime.php | 86 + .../library/Helpers/CanValidateIterable.php | 33 + .../library/Helpers/CanValidateUndefined.php | 30 + .../library/Helpers/CountryInfo.php | 54 + .../validation/library/Helpers/DomainInfo.php | 46 + .../validation/library/Message/Formatter.php | 54 + .../library/Message/ParameterStringifier.php | 18 + .../Stringifier/KeepOriginalStringName.php | 30 + .../validation/library/NonNegatable.php | 18 + .../validation/library/Rules/AbstractAge.php | 98 + .../library/Rules/AbstractComparison.php | 60 + .../library/Rules/AbstractComposite.php | 150 + .../library/Rules/AbstractEnvelope.php | 61 + .../library/Rules/AbstractFilterRule.php | 61 + .../library/Rules/AbstractRelated.php | 154 + .../validation/library/Rules/AbstractRule.php | 126 + .../library/Rules/AbstractSearcher.php | 50 + .../library/Rules/AbstractWrapper.php | 68 + .../validation/library/Rules/AllOf.php | 67 + .../validation/library/Rules/Alnum.php | 33 + .../validation/library/Rules/Alpha.php | 30 + .../library/Rules/AlwaysInvalid.php | 28 + .../validation/library/Rules/AlwaysValid.php | 28 + .../validation/library/Rules/AnyOf.php | 78 + .../validation/library/Rules/ArrayType.php | 31 + .../validation/library/Rules/ArrayVal.php | 35 + .../validation/library/Rules/Attribute.php | 53 + .../validation/library/Rules/Base.php | 64 + .../validation/library/Rules/Base64.php | 40 + .../validation/library/Rules/Between.php | 50 + .../validation/library/Rules/BoolType.php | 29 + .../validation/library/Rules/BoolVal.php | 34 + .../validation/library/Rules/Bsn.php | 55 + .../validation/library/Rules/Call.php | 107 + .../validation/library/Rules/CallableType.php | 28 + .../validation/library/Rules/Callback.php | 67 + .../validation/library/Rules/Charset.php | 55 + .../validation/library/Rules/Cnh.php | 59 + .../validation/library/Rules/Cnpj.php | 83 + .../validation/library/Rules/Consonant.php | 30 + .../validation/library/Rules/Contains.php | 78 + .../validation/library/Rules/ContainsAny.php | 50 + .../validation/library/Rules/Control.php | 31 + .../validation/library/Rules/Countable.php | 32 + .../validation/library/Rules/CountryCode.php | 375 + .../validation/library/Rules/Cpf.php | 59 + .../validation/library/Rules/CreditCard.php | 102 + .../validation/library/Rules/CurrencyCode.php | 212 + .../validation/library/Rules/Date.php | 67 + .../validation/library/Rules/DateTime.php | 66 + .../validation/library/Rules/Decimal.php | 71 + .../validation/library/Rules/Digit.php | 30 + .../validation/library/Rules/Directory.php | 45 + .../validation/library/Rules/Domain.php | 180 + .../validation/library/Rules/Each.php | 96 + .../validation/library/Rules/Email.php | 70 + .../validation/library/Rules/EndsWith.php | 82 + .../validation/library/Rules/Equals.php | 43 + .../validation/library/Rules/Equivalent.php | 57 + .../validation/library/Rules/Even.php | 36 + .../validation/library/Rules/Executable.php | 40 + .../validation/library/Rules/Exists.php | 34 + .../validation/library/Rules/Extension.php | 55 + .../validation/library/Rules/Factor.php | 61 + .../validation/library/Rules/FalseVal.php | 32 + .../validation/library/Rules/Fibonacci.php | 41 + .../validation/library/Rules/File.php | 36 + .../validation/library/Rules/FilterVar.php | 70 + .../validation/library/Rules/Finite.php | 30 + .../validation/library/Rules/FloatType.php | 29 + .../validation/library/Rules/FloatVal.php | 34 + .../validation/library/Rules/Graph.php | 31 + .../validation/library/Rules/GreaterThan.php | 26 + .../validation/library/Rules/HexRgbColor.php | 24 + .../validation/library/Rules/Iban.php | 149 + .../validation/library/Rules/Identical.php | 41 + .../validation/library/Rules/Image.php | 62 + .../validation/library/Rules/Imei.php | 46 + .../workerman/validation/library/Rules/In.php | 90 + .../validation/library/Rules/Infinite.php | 30 + .../validation/library/Rules/Instance.php | 41 + .../validation/library/Rules/IntType.php | 28 + .../validation/library/Rules/IntVal.php | 42 + .../workerman/validation/library/Rules/Ip.php | 209 + .../validation/library/Rules/Isbn.php | 45 + .../validation/library/Rules/IterableType.php | 30 + .../validation/library/Rules/Json.php | 44 + .../validation/library/Rules/Key.php | 53 + .../validation/library/Rules/KeyNested.php | 146 + .../validation/library/Rules/KeySet.php | 142 + .../validation/library/Rules/KeyValue.php | 144 + .../validation/library/Rules/LanguageCode.php | 549 + .../validation/library/Rules/LeapDate.php | 54 + .../validation/library/Rules/LeapYear.php | 50 + .../validation/library/Rules/Length.php | 130 + .../validation/library/Rules/LessThan.php | 26 + .../validation/library/Rules/Lowercase.php | 36 + .../validation/library/Rules/Luhn.php | 58 + .../validation/library/Rules/MacAddress.php | 36 + .../validation/library/Rules/Max.php | 27 + .../validation/library/Rules/MaxAge.php | 27 + .../validation/library/Rules/Mimetype.php | 66 + .../validation/library/Rules/Min.php | 27 + .../validation/library/Rules/MinAge.php | 29 + .../validation/library/Rules/Mobile.php | 30 + .../validation/library/Rules/Multiple.php | 40 + .../validation/library/Rules/Negative.php | 34 + .../validation/library/Rules/NfeAccessKey.php | 56 + .../validation/library/Rules/Nif.php | 99 + .../validation/library/Rules/Nip.php | 54 + .../workerman/validation/library/Rules/No.php | 32 + .../validation/library/Rules/NoWhitespace.php | 41 + .../validation/library/Rules/NoneOf.php | 52 + .../validation/library/Rules/Not.php | 128 + .../validation/library/Rules/NotBlank.php | 51 + .../validation/library/Rules/NotEmoji.php | 206 + .../validation/library/Rules/NotEmpty.php | 35 + .../validation/library/Rules/NotOptional.php | 33 + .../validation/library/Rules/NullType.php | 29 + .../validation/library/Rules/Nullable.php | 54 + .../validation/library/Rules/Number.php | 35 + .../validation/library/Rules/NumericVal.php | 30 + .../validation/library/Rules/ObjectType.php | 29 + .../validation/library/Rules/Odd.php | 41 + .../validation/library/Rules/OneOf.php | 82 + .../validation/library/Rules/Optional.php | 56 + .../library/Rules/PerfectSquare.php | 33 + .../validation/library/Rules/Pesel.php | 51 + .../validation/library/Rules/Phone.php | 73 + .../validation/library/Rules/PhpLabel.php | 31 + .../validation/library/Rules/Pis.php | 53 + .../validation/library/Rules/PolishIdCard.php | 63 + .../library/Rules/PortugueseNif.php | 105 + .../validation/library/Rules/Positive.php | 34 + .../validation/library/Rules/PostalCode.php | 222 + .../validation/library/Rules/PrimeNumber.php | 48 + .../validation/library/Rules/Printable.php | 32 + .../library/Rules/PublicDomainSuffix.php | 37 + .../validation/library/Rules/Punct.php | 31 + .../validation/library/Rules/Readable.php | 41 + .../validation/library/Rules/Regex.php | 48 + .../validation/library/Rules/ResourceType.php | 28 + .../validation/library/Rules/Roman.php | 25 + .../validation/library/Rules/ScalarVal.php | 28 + .../validation/library/Rules/Size.php | 124 + .../validation/library/Rules/Slug.php | 41 + .../validation/library/Rules/Sorted.php | 94 + .../validation/library/Rules/Space.php | 31 + .../validation/library/Rules/StartsWith.php | 89 + .../validation/library/Rules/StringType.php | 29 + .../validation/library/Rules/StringVal.php | 31 + .../library/Rules/SubdivisionCode.php | 52 + .../validation/library/Rules/Subset.php | 49 + .../validation/library/Rules/SymbolicLink.php | 36 + .../validation/library/Rules/Time.php | 66 + .../validation/library/Rules/Tld.php | 256 + .../validation/library/Rules/TrueVal.php | 32 + .../validation/library/Rules/Type.php | 86 + .../validation/library/Rules/Unique.php | 37 + .../validation/library/Rules/Uploaded.php | 45 + .../validation/library/Rules/Uppercase.php | 36 + .../validation/library/Rules/Url.php | 32 + .../validation/library/Rules/Uuid.php | 80 + .../validation/library/Rules/Version.php | 36 + .../validation/library/Rules/VideoUrl.php | 90 + .../validation/library/Rules/Vowel.php | 29 + .../validation/library/Rules/When.php | 91 + .../validation/library/Rules/Writable.php | 41 + .../validation/library/Rules/Xdigit.php | 27 + .../validation/library/Rules/Yes.php | 59 + .../validation/library/StaticValidator.php | 375 + .../validation/library/Validatable.php | 48 + .../validation/library/Validator.php | 99 + .../workerman/webman-framework/.gitignore | 5 + .../workerman/webman-framework/README.md | 5 + .../workerman/webman-framework/composer.json | 47 + .../workerman/webman-framework/src/App.php | 939 ++ .../webman-framework/src/Bootstrap.php | 28 + .../workerman/webman-framework/src/Config.php | 296 + .../webman-framework/src/Container.php | 84 + .../webman-framework/src/Context.php | 129 + .../src/Exception/ExceptionHandler.php | 118 + .../Exception/ExceptionHandlerInterface.php | 35 + .../src/Exception/FileException.php | 25 + .../src/Exception/NotFoundException.php | 25 + .../workerman/webman-framework/src/File.php | 56 + .../src/FileSessionHandler.php | 25 + .../webman-framework/src/Http/Request.php | 318 + .../webman-framework/src/Http/Response.php | 87 + .../webman-framework/src/Http/UploadFile.php | 111 + .../webman-framework/src/Install.php | 59 + .../webman-framework/src/Middleware.php | 90 + .../src/MiddlewareInterface.php | 30 + .../workerman/webman-framework/src/Route.php | 470 + .../webman-framework/src/Route/Route.php | 199 + .../src/Session/FileSessionHandler.php | 26 + .../Session/RedisClusterSessionHandler.php | 22 + .../src/Session/RedisSessionHandler.php | 26 + .../workerman/webman-framework/src/Util.php | 44 + .../workerman/webman-framework/src/View.php | 27 + .../webman-framework/src/support/App.php | 151 + .../webman-framework/src/support/Cache.php | 50 + .../src/support/Container.php | 48 + .../webman-framework/src/support/Context.php | 25 + .../webman-framework/src/support/Db.php | 36 + .../webman-framework/src/support/Log.php | 139 + .../webman-framework/src/support/Model.php | 262 + .../webman-framework/src/support/Plugin.php | 108 + .../webman-framework/src/support/Redis.php | 283 + .../webman-framework/src/support/Request.php | 24 + .../webman-framework/src/support/Response.php | 24 + .../src/support/Translation.php | 104 + .../webman-framework/src/support/View.php | 35 + .../src/support/bootstrap/LaravelDb.php | 123 + .../src/support/bootstrap/Session.php | 61 + .../support/exception/BusinessException.php | 38 + .../src/support/exception/Handler.php | 47 + .../src/support/view/Blade.php | 79 + .../webman-framework/src/support/view/Raw.php | 84 + .../src/support/view/ThinkPHP.php | 81 + .../src/support/view/Twig.php | 82 + .../workerman/workerman/.github/FUNDING.yml | 4 + cacme/vendor/workerman/workerman/.gitignore | 6 + .../vendor/workerman/workerman/Autoloader.php | 69 + .../Connection/AsyncTcpConnection.php | 378 + .../Connection/AsyncUdpConnection.php | 203 + .../Connection/ConnectionInterface.php | 126 + .../workerman/Connection/TcpConnection.php | 982 ++ .../workerman/Connection/UdpConnection.php | 208 + .../vendor/workerman/workerman/Events/Ev.php | 189 + .../workerman/workerman/Events/Event.php | 215 + .../workerman/Events/EventInterface.php | 107 + .../workerman/workerman/Events/Libevent.php | 225 + .../workerman/workerman/Events/React/Base.php | 264 + .../workerman/Events/React/ExtEventLoop.php | 27 + .../Events/React/ExtLibEventLoop.php | 27 + .../Events/React/StreamSelectLoop.php | 26 + .../workerman/workerman/Events/Select.php | 357 + .../workerman/workerman/Events/Swoole.php | 230 + .../vendor/workerman/workerman/Events/Uv.php | 260 + .../workerman/workerman/Lib/Constants.php | 44 + .../vendor/workerman/workerman/Lib/Timer.php | 22 + .../workerman/workerman/MIT-LICENSE.txt | 21 + .../workerman/workerman/Protocols/Frame.php | 61 + .../workerman/workerman/Protocols/Http.php | 323 + .../workerman/Protocols/Http/Chunk.php | 48 + .../workerman/Protocols/Http/Request.php | 694 + .../workerman/Protocols/Http/Response.php | 458 + .../Protocols/Http/ServerSentEvents.php | 64 + .../workerman/Protocols/Http/Session.php | 461 + .../Http/Session/FileSessionHandler.php | 183 + .../Session/RedisClusterSessionHandler.php | 46 + .../Http/Session/RedisSessionHandler.php | 154 + .../Http/Session/SessionHandlerInterface.php | 114 + .../workerman/Protocols/Http/mime.types | 90 + .../workerman/Protocols/ProtocolInterface.php | 52 + .../workerman/workerman/Protocols/Text.php | 70 + .../workerman/Protocols/Websocket.php | 564 + .../workerman/workerman/Protocols/Ws.php | 432 + cacme/vendor/workerman/workerman/README.md | 342 + cacme/vendor/workerman/workerman/Timer.php | 220 + cacme/vendor/workerman/workerman/Worker.php | 2672 ++++ .../vendor/workerman/workerman/composer.json | 38 + cacme/vendor/yzh52521/easyhttp/LICENSE | 22 + cacme/vendor/yzh52521/easyhttp/README.md | 415 + cacme/vendor/yzh52521/easyhttp/composer.json | 33 + .../easyhttp/src/ConnectionException.php | 10 + cacme/vendor/yzh52521/easyhttp/src/Facade.php | 26 + cacme/vendor/yzh52521/easyhttp/src/Http.php | 64 + cacme/vendor/yzh52521/easyhttp/src/Logger.php | 273 + .../vendor/yzh52521/easyhttp/src/Request.php | 711 + .../easyhttp/src/RequestException.php | 43 + .../vendor/yzh52521/easyhttp/src/Response.php | 212 + cacme/vendor/yzh52521/easyhttp/src/Retry.php | 46 + cacme/webman | 57 + cacme/windows.bat | 3 + cacme/windows.php | 118 + index.html | 132 + xb.php | 346 + 1779 files changed, 171774 insertions(+) create mode 100644 404.html create mode 160000 acme create mode 100644 acme.sh create mode 100644 cacme/.gitignore create mode 100644 cacme/LICENSE create mode 100644 cacme/README.md create mode 100644 cacme/app/command/Acme.php create mode 100644 cacme/app/controller/Apply.php create mode 100644 cacme/app/controller/IndexController.php create mode 100644 cacme/app/functions.php create mode 100644 cacme/app/middleware/StaticFile.php create mode 100644 cacme/app/model/Test.php create mode 100644 cacme/app/view/index.html create mode 100644 cacme/composer.json create mode 100644 cacme/composer.lock create mode 100644 cacme/config/app.php create mode 100644 cacme/config/autoload.php create mode 100644 cacme/config/bootstrap.php create mode 100644 cacme/config/container.php create mode 100644 cacme/config/database.php create mode 100644 cacme/config/dependence.php create mode 100644 cacme/config/exception.php create mode 100644 cacme/config/log.php create mode 100644 cacme/config/middleware.php create mode 100644 cacme/config/plugin/webman/console/app.php create mode 100644 cacme/config/process.php create mode 100644 cacme/config/redis.php create mode 100644 cacme/config/route.php create mode 100644 cacme/config/server.php create mode 100644 cacme/config/session.php create mode 100644 cacme/config/static.php create mode 100644 cacme/config/translation.php create mode 100644 cacme/config/view.php create mode 100644 cacme/process/Monitor.php create mode 100644 cacme/public/404.html create mode 100644 cacme/public/favicon.ico create mode 100644 cacme/public/jquery-3.7.1.js create mode 100644 cacme/public/normal.css create mode 100644 cacme/public/sakura.css create mode 100644 cacme/runtime/.gitignore create mode 100644 cacme/runtime/logs/.gitignore create mode 100644 cacme/runtime/views/.gitignore create mode 100755 cacme/start.php create mode 100644 cacme/support/Request.php create mode 100644 cacme/support/Response.php create mode 100644 cacme/support/bootstrap.php create mode 100644 cacme/support/helpers.php create mode 100644 cacme/vendor/acmephp/core/.gitignore create mode 100644 cacme/vendor/acmephp/core/AcmeClient.php create mode 100644 cacme/vendor/acmephp/core/AcmeClientInterface.php create mode 100644 cacme/vendor/acmephp/core/Challenge/ChainValidator.php create mode 100644 cacme/vendor/acmephp/core/Challenge/ConfigurableServiceInterface.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/DnsDataExtractor.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/DnsResolverInterface.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/DnsValidator.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/GandiSolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/LibDnsResolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/Route53Solver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/SimpleDnsResolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Dns/SimpleDnsSolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Http/FilesystemSolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Http/HttpDataExtractor.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Http/HttpValidator.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Http/MockHttpValidator.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Http/MockServerHttpSolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/Http/SimpleHttpSolver.php create mode 100644 cacme/vendor/acmephp/core/Challenge/MultipleChallengesSolverInterface.php create mode 100644 cacme/vendor/acmephp/core/Challenge/SolverInterface.php create mode 100644 cacme/vendor/acmephp/core/Challenge/ValidatorInterface.php create mode 100644 cacme/vendor/acmephp/core/Challenge/WaitingValidator.php create mode 100644 cacme/vendor/acmephp/core/Exception/AcmeCoreClientException.php create mode 100644 cacme/vendor/acmephp/core/Exception/AcmeCoreException.php create mode 100644 cacme/vendor/acmephp/core/Exception/AcmeCoreServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/AcmeDnsResolutionException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/CertificateRequestFailedException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/CertificateRequestTimedOutException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/CertificateRevocationException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/ChallengeFailedException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/ChallengeNotSupportedException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/ChallengeTimedOutException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/ExpectedJsonException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Protocol/ProtocolException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/BadCsrServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/BadNonceServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/CaaServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/ConnectionServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/DnsServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/IncorrectResponseServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/InternalServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/InvalidContactServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/InvalidEmailServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/MalformedServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/OrderNotReadyServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/RateLimitedServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/RejectedIdentifierServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/TlsServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/UnauthorizedServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/UnknownHostServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/UnsupportedContactServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/UnsupportedIdentifierServerException.php create mode 100644 cacme/vendor/acmephp/core/Exception/Server/UserActionRequiredServerException.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/Adapter/FlysystemAdapter.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/Adapter/FlysystemFtpFactory.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/Adapter/FlysystemLocalFactory.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/Adapter/FlysystemSftpFactory.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/Adapter/NullAdapter.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/FilesystemFactoryInterface.php create mode 100644 cacme/vendor/acmephp/core/Filesystem/FilesystemInterface.php create mode 100644 cacme/vendor/acmephp/core/Http/Base64SafeEncoder.php create mode 100644 cacme/vendor/acmephp/core/Http/SecureHttpClient.php create mode 100644 cacme/vendor/acmephp/core/Http/SecureHttpClientFactory.php create mode 100644 cacme/vendor/acmephp/core/Http/ServerErrorHandler.php create mode 100644 cacme/vendor/acmephp/core/LICENSE create mode 100644 cacme/vendor/acmephp/core/Protocol/AuthorizationChallenge.php create mode 100644 cacme/vendor/acmephp/core/Protocol/CertificateOrder.php create mode 100644 cacme/vendor/acmephp/core/Protocol/ExternalAccount.php create mode 100644 cacme/vendor/acmephp/core/Protocol/ResourcesDirectory.php create mode 100644 cacme/vendor/acmephp/core/Protocol/RevocationReason.php create mode 100644 cacme/vendor/acmephp/core/README.md create mode 100644 cacme/vendor/acmephp/core/Util/JsonDecoder.php create mode 100644 cacme/vendor/acmephp/core/composer.json create mode 100644 cacme/vendor/acmephp/ssl/.gitignore create mode 100644 cacme/vendor/acmephp/ssl/Certificate.php create mode 100644 cacme/vendor/acmephp/ssl/CertificateRequest.php create mode 100644 cacme/vendor/acmephp/ssl/CertificateResponse.php create mode 100644 cacme/vendor/acmephp/ssl/DistinguishedName.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/AcmeSslException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/CSRSigningException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/CertificateFormatException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/CertificateParsingException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/DataSigningException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/KeyFormatException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/KeyGenerationException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/KeyPairGenerationException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/KeyParsingException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/ParsingException.php create mode 100644 cacme/vendor/acmephp/ssl/Exception/SigningException.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/ChainPrivateKeyGenerator.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/DhKey/DhKeyGenerator.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/DhKey/DhKeyOption.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/DsaKey/DsaKeyGenerator.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/DsaKey/DsaKeyOption.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/EcKey/EcKeyGenerator.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/EcKey/EcKeyOption.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/KeyOption.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/KeyPairGenerator.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/OpensslPrivateKeyGeneratorTrait.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/PrivateKeyGeneratorInterface.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/RsaKey/RsaKeyGenerator.php create mode 100644 cacme/vendor/acmephp/ssl/Generator/RsaKey/RsaKeyOption.php create mode 100644 cacme/vendor/acmephp/ssl/Key.php create mode 100644 cacme/vendor/acmephp/ssl/KeyPair.php create mode 100644 cacme/vendor/acmephp/ssl/LICENSE create mode 100644 cacme/vendor/acmephp/ssl/ParsedCertificate.php create mode 100644 cacme/vendor/acmephp/ssl/ParsedKey.php create mode 100644 cacme/vendor/acmephp/ssl/Parser/CertificateParser.php create mode 100644 cacme/vendor/acmephp/ssl/Parser/KeyParser.php create mode 100644 cacme/vendor/acmephp/ssl/PrivateKey.php create mode 100644 cacme/vendor/acmephp/ssl/PublicKey.php create mode 100644 cacme/vendor/acmephp/ssl/README.md create mode 100644 cacme/vendor/acmephp/ssl/Signer/CertificateRequestSigner.php create mode 100644 cacme/vendor/acmephp/ssl/Signer/DataSigner.php create mode 100644 cacme/vendor/acmephp/ssl/composer.json create mode 100644 cacme/vendor/autoload.php create mode 100644 cacme/vendor/composer/ClassLoader.php create mode 100644 cacme/vendor/composer/InstalledVersions.php create mode 100644 cacme/vendor/composer/LICENSE create mode 100644 cacme/vendor/composer/autoload_classmap.php create mode 100644 cacme/vendor/composer/autoload_files.php create mode 100644 cacme/vendor/composer/autoload_namespaces.php create mode 100644 cacme/vendor/composer/autoload_psr4.php create mode 100644 cacme/vendor/composer/autoload_real.php create mode 100644 cacme/vendor/composer/autoload_static.php create mode 100644 cacme/vendor/composer/installed.json create mode 100644 cacme/vendor/composer/installed.php create mode 100644 cacme/vendor/composer/platform_check.php create mode 100644 cacme/vendor/doctrine/inflector/LICENSE create mode 100644 cacme/vendor/doctrine/inflector/README.md create mode 100644 cacme/vendor/doctrine/inflector/composer.json create mode 100644 cacme/vendor/doctrine/inflector/docs/en/index.rst create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/CachedWordInflector.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/GenericLanguageInflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Inflector.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Language.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/LanguageInflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/NoopWordInflector.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Inflectible.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Rules.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Uninflected.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Inflectible.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Rules.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Uninflected.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Inflectible.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Rules.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Uninflected.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Pattern.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Patterns.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Inflectible.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Rules.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Uninflected.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Ruleset.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/Inflectible.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/Rules.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/Uninflected.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Substitution.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Substitutions.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Transformation.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Transformations.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/Inflectible.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/InflectorFactory.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/Rules.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/Uninflected.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Word.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/RulesetInflector.php create mode 100644 cacme/vendor/doctrine/inflector/lib/Doctrine/Inflector/WordInflector.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/CHANGELOG.md create mode 100644 cacme/vendor/guzzlehttp/guzzle/LICENSE create mode 100644 cacme/vendor/guzzlehttp/guzzle/README.md create mode 100644 cacme/vendor/guzzlehttp/guzzle/UPGRADING.md create mode 100644 cacme/vendor/guzzlehttp/guzzle/composer.json create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/BodySummarizer.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Client.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/ClientInterface.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/ClientTrait.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/HandlerStack.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/MessageFormatter.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Middleware.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Pool.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/RequestOptions.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/TransferStats.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/Utils.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/functions.php create mode 100644 cacme/vendor/guzzlehttp/guzzle/src/functions_include.php create mode 100644 cacme/vendor/guzzlehttp/promises/CHANGELOG.md create mode 100644 cacme/vendor/guzzlehttp/promises/LICENSE create mode 100644 cacme/vendor/guzzlehttp/promises/README.md create mode 100644 cacme/vendor/guzzlehttp/promises/composer.json create mode 100644 cacme/vendor/guzzlehttp/promises/src/AggregateException.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/CancellationException.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/Coroutine.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/Create.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/Each.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/EachPromise.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/FulfilledPromise.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/Is.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/Promise.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/PromiseInterface.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/PromisorInterface.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/RejectedPromise.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/RejectionException.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/TaskQueue.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/TaskQueueInterface.php create mode 100644 cacme/vendor/guzzlehttp/promises/src/Utils.php create mode 100644 cacme/vendor/guzzlehttp/psr7/CHANGELOG.md create mode 100644 cacme/vendor/guzzlehttp/psr7/LICENSE create mode 100644 cacme/vendor/guzzlehttp/psr7/README.md create mode 100644 cacme/vendor/guzzlehttp/psr7/composer.json create mode 100644 cacme/vendor/guzzlehttp/psr7/src/AppendStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/BufferStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/CachingStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/DroppingStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/FnStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Header.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/HttpFactory.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/InflateStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/LazyOpenStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/LimitStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Message.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/MessageTrait.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/MimeType.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/MultipartStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/NoSeekStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/PumpStream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Query.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Request.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Response.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Rfc7230.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/ServerRequest.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Stream.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/StreamWrapper.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/UploadedFile.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Uri.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/UriComparator.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/UriNormalizer.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/UriResolver.php create mode 100644 cacme/vendor/guzzlehttp/psr7/src/Utils.php create mode 100644 cacme/vendor/lcobucci/clock/LICENSE create mode 100644 cacme/vendor/lcobucci/clock/composer.json create mode 100644 cacme/vendor/lcobucci/clock/src/Clock.php create mode 100644 cacme/vendor/lcobucci/clock/src/FrozenClock.php create mode 100644 cacme/vendor/lcobucci/clock/src/SystemClock.php create mode 100644 cacme/vendor/lcobucci/jwt/LICENSE create mode 100644 cacme/vendor/lcobucci/jwt/composer.json create mode 100644 cacme/vendor/lcobucci/jwt/src/Builder.php create mode 100644 cacme/vendor/lcobucci/jwt/src/ClaimsFormatter.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Configuration.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Decoder.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoder.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/CannotDecodeContent.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/CannotEncodeContent.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/ChainedFormatter.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/JoseEncoder.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/MicrosecondBasedDateConversion.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/UnifyAudience.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Encoding/UnixTimestampDates.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Exception.php create mode 100644 cacme/vendor/lcobucci/jwt/src/JwtFacade.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Parser.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Blake2b.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/CannotSignPayload.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/ConversionFailed.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/MultibyteStringConverter.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha256.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha384.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha512.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/SignatureConverter.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/UnsafeSha256.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/UnsafeSha384.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Ecdsa/UnsafeSha512.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Eddsa.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac/Sha256.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac/Sha384.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac/Sha512.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac/UnsafeSha256.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac/UnsafeSha384.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Hmac/UnsafeSha512.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/InvalidKeyProvided.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Key.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Key/FileCouldNotBeRead.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Key/InMemory.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Key/LocalFileReference.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/None.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/OpenSSL.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa/Sha256.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa/Sha384.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa/Sha512.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa/UnsafeSha256.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa/UnsafeSha384.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/Rsa/UnsafeSha512.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/UnsafeEcdsa.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Signer/UnsafeRsa.php create mode 100644 cacme/vendor/lcobucci/jwt/src/SodiumBase64Polyfill.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/Builder.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/DataSet.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/InvalidTokenStructure.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/Parser.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/Plain.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/RegisteredClaimGiven.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/RegisteredClaims.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/Signature.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Token/UnsupportedHeaderFound.php create mode 100644 cacme/vendor/lcobucci/jwt/src/UnencryptedToken.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/CannotValidateARegisteredClaim.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/HasClaimWithValue.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/IdentifiedBy.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/IssuedBy.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/LeewayCannotBeNegative.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/LooseValidAt.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/PermittedFor.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/RelatedTo.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/SignedWith.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/StrictValidAt.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Constraint/ValidAt.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/ConstraintViolation.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/NoConstraintsGiven.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/RequiredConstraintsViolated.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/SignedWith.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/ValidAt.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validation/Validator.php create mode 100644 cacme/vendor/lcobucci/jwt/src/Validator.php create mode 100644 cacme/vendor/monolog/monolog/CHANGELOG.md create mode 100644 cacme/vendor/monolog/monolog/LICENSE create mode 100644 cacme/vendor/monolog/monolog/README.md create mode 100644 cacme/vendor/monolog/monolog/UPGRADE.md create mode 100644 cacme/vendor/monolog/monolog/composer.json create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/ErrorHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/Handler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/LogRecord.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Logger.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Registry.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/ResettableInterface.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/SignalHandler.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Test/TestCase.php create mode 100644 cacme/vendor/monolog/monolog/src/Monolog/Utils.php create mode 100644 cacme/vendor/nikic/fast-route/.gitignore create mode 100644 cacme/vendor/nikic/fast-route/.hhconfig create mode 100644 cacme/vendor/nikic/fast-route/.travis.yml create mode 100644 cacme/vendor/nikic/fast-route/FastRoute.hhi create mode 100644 cacme/vendor/nikic/fast-route/LICENSE create mode 100644 cacme/vendor/nikic/fast-route/README.md create mode 100644 cacme/vendor/nikic/fast-route/composer.json create mode 100644 cacme/vendor/nikic/fast-route/phpunit.xml create mode 100644 cacme/vendor/nikic/fast-route/psalm.xml create mode 100644 cacme/vendor/nikic/fast-route/src/BadRouteException.php create mode 100644 cacme/vendor/nikic/fast-route/src/DataGenerator.php create mode 100644 cacme/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php create mode 100644 cacme/vendor/nikic/fast-route/src/Dispatcher.php create mode 100644 cacme/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php create mode 100644 cacme/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php create mode 100644 cacme/vendor/nikic/fast-route/src/Route.php create mode 100644 cacme/vendor/nikic/fast-route/src/RouteCollector.php create mode 100644 cacme/vendor/nikic/fast-route/src/RouteParser.php create mode 100644 cacme/vendor/nikic/fast-route/src/RouteParser/Std.php create mode 100644 cacme/vendor/nikic/fast-route/src/bootstrap.php create mode 100644 cacme/vendor/nikic/fast-route/src/functions.php create mode 100644 cacme/vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php create mode 100644 cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php create mode 100644 cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php create mode 100644 cacme/vendor/nikic/fast-route/test/RouteCollectorTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/RouteParser/StdTest.php create mode 100644 cacme/vendor/nikic/fast-route/test/bootstrap.php create mode 100644 cacme/vendor/psr/clock/CHANGELOG.md create mode 100644 cacme/vendor/psr/clock/LICENSE create mode 100644 cacme/vendor/psr/clock/README.md create mode 100644 cacme/vendor/psr/clock/composer.json create mode 100644 cacme/vendor/psr/clock/src/ClockInterface.php create mode 100644 cacme/vendor/psr/container/.gitignore create mode 100644 cacme/vendor/psr/container/LICENSE create mode 100644 cacme/vendor/psr/container/README.md create mode 100644 cacme/vendor/psr/container/composer.json create mode 100644 cacme/vendor/psr/container/src/ContainerExceptionInterface.php create mode 100644 cacme/vendor/psr/container/src/ContainerInterface.php create mode 100644 cacme/vendor/psr/container/src/NotFoundExceptionInterface.php create mode 100644 cacme/vendor/psr/http-client/CHANGELOG.md create mode 100644 cacme/vendor/psr/http-client/LICENSE create mode 100644 cacme/vendor/psr/http-client/README.md create mode 100644 cacme/vendor/psr/http-client/composer.json create mode 100644 cacme/vendor/psr/http-client/src/ClientExceptionInterface.php create mode 100644 cacme/vendor/psr/http-client/src/ClientInterface.php create mode 100644 cacme/vendor/psr/http-client/src/NetworkExceptionInterface.php create mode 100644 cacme/vendor/psr/http-client/src/RequestExceptionInterface.php create mode 100644 cacme/vendor/psr/http-factory/LICENSE create mode 100644 cacme/vendor/psr/http-factory/README.md create mode 100644 cacme/vendor/psr/http-factory/composer.json create mode 100644 cacme/vendor/psr/http-factory/src/RequestFactoryInterface.php create mode 100644 cacme/vendor/psr/http-factory/src/ResponseFactoryInterface.php create mode 100644 cacme/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php create mode 100644 cacme/vendor/psr/http-factory/src/StreamFactoryInterface.php create mode 100644 cacme/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php create mode 100644 cacme/vendor/psr/http-factory/src/UriFactoryInterface.php create mode 100644 cacme/vendor/psr/http-message/CHANGELOG.md create mode 100644 cacme/vendor/psr/http-message/LICENSE create mode 100644 cacme/vendor/psr/http-message/README.md create mode 100644 cacme/vendor/psr/http-message/composer.json create mode 100644 cacme/vendor/psr/http-message/docs/PSR7-Interfaces.md create mode 100644 cacme/vendor/psr/http-message/docs/PSR7-Usage.md create mode 100644 cacme/vendor/psr/http-message/src/MessageInterface.php create mode 100644 cacme/vendor/psr/http-message/src/RequestInterface.php create mode 100644 cacme/vendor/psr/http-message/src/ResponseInterface.php create mode 100644 cacme/vendor/psr/http-message/src/ServerRequestInterface.php create mode 100644 cacme/vendor/psr/http-message/src/StreamInterface.php create mode 100644 cacme/vendor/psr/http-message/src/UploadedFileInterface.php create mode 100644 cacme/vendor/psr/http-message/src/UriInterface.php create mode 100644 cacme/vendor/psr/log/LICENSE create mode 100644 cacme/vendor/psr/log/README.md create mode 100644 cacme/vendor/psr/log/composer.json create mode 100644 cacme/vendor/psr/log/src/AbstractLogger.php create mode 100644 cacme/vendor/psr/log/src/InvalidArgumentException.php create mode 100644 cacme/vendor/psr/log/src/LogLevel.php create mode 100644 cacme/vendor/psr/log/src/LoggerAwareInterface.php create mode 100644 cacme/vendor/psr/log/src/LoggerAwareTrait.php create mode 100644 cacme/vendor/psr/log/src/LoggerInterface.php create mode 100644 cacme/vendor/psr/log/src/LoggerTrait.php create mode 100644 cacme/vendor/psr/log/src/NullLogger.php create mode 100644 cacme/vendor/ralouphie/getallheaders/LICENSE create mode 100644 cacme/vendor/ralouphie/getallheaders/README.md create mode 100644 cacme/vendor/ralouphie/getallheaders/composer.json create mode 100644 cacme/vendor/ralouphie/getallheaders/src/getallheaders.php create mode 100644 cacme/vendor/respect/stringifier/LICENSE.md create mode 100644 cacme/vendor/respect/stringifier/README.md create mode 100644 cacme/vendor/respect/stringifier/composer.json create mode 100644 cacme/vendor/respect/stringifier/src/Quoter.php create mode 100644 cacme/vendor/respect/stringifier/src/Quoters/CodeQuoter.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/ArrayStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/BoolStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/ClusterStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/DateTimeStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/InfiniteStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/JsonParsableStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/JsonSerializableStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/NanStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/NullStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/ObjectStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/ResourceStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/StringableObjectStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/ThrowableStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/Stringifiers/TraversableStringifier.php create mode 100644 cacme/vendor/respect/stringifier/src/stringify.php create mode 100644 cacme/vendor/stella-maris/clock/.editorconfig create mode 100644 cacme/vendor/stella-maris/clock/LICENSE.md create mode 100644 cacme/vendor/stella-maris/clock/README.md create mode 100644 cacme/vendor/stella-maris/clock/composer.json create mode 100644 cacme/vendor/stella-maris/clock/src/ClockInterface.php create mode 100644 cacme/vendor/symfony/console/Application.php create mode 100644 cacme/vendor/symfony/console/Attribute/AsCommand.php create mode 100644 cacme/vendor/symfony/console/CHANGELOG.md create mode 100644 cacme/vendor/symfony/console/CI/GithubActionReporter.php create mode 100644 cacme/vendor/symfony/console/Color.php create mode 100644 cacme/vendor/symfony/console/Command/Command.php create mode 100644 cacme/vendor/symfony/console/Command/CompleteCommand.php create mode 100644 cacme/vendor/symfony/console/Command/DumpCompletionCommand.php create mode 100644 cacme/vendor/symfony/console/Command/HelpCommand.php create mode 100644 cacme/vendor/symfony/console/Command/LazyCommand.php create mode 100644 cacme/vendor/symfony/console/Command/ListCommand.php create mode 100644 cacme/vendor/symfony/console/Command/LockableTrait.php create mode 100644 cacme/vendor/symfony/console/Command/SignalableCommandInterface.php create mode 100644 cacme/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php create mode 100644 cacme/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php create mode 100644 cacme/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php create mode 100644 cacme/vendor/symfony/console/Completion/CompletionInput.php create mode 100644 cacme/vendor/symfony/console/Completion/CompletionSuggestions.php create mode 100644 cacme/vendor/symfony/console/Completion/Output/BashCompletionOutput.php create mode 100644 cacme/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php create mode 100644 cacme/vendor/symfony/console/Completion/Suggestion.php create mode 100644 cacme/vendor/symfony/console/ConsoleEvents.php create mode 100644 cacme/vendor/symfony/console/Cursor.php create mode 100644 cacme/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php create mode 100644 cacme/vendor/symfony/console/Descriptor/ApplicationDescription.php create mode 100644 cacme/vendor/symfony/console/Descriptor/Descriptor.php create mode 100644 cacme/vendor/symfony/console/Descriptor/DescriptorInterface.php create mode 100644 cacme/vendor/symfony/console/Descriptor/JsonDescriptor.php create mode 100644 cacme/vendor/symfony/console/Descriptor/MarkdownDescriptor.php create mode 100644 cacme/vendor/symfony/console/Descriptor/TextDescriptor.php create mode 100644 cacme/vendor/symfony/console/Descriptor/XmlDescriptor.php create mode 100644 cacme/vendor/symfony/console/Event/ConsoleCommandEvent.php create mode 100644 cacme/vendor/symfony/console/Event/ConsoleErrorEvent.php create mode 100644 cacme/vendor/symfony/console/Event/ConsoleEvent.php create mode 100644 cacme/vendor/symfony/console/Event/ConsoleSignalEvent.php create mode 100644 cacme/vendor/symfony/console/Event/ConsoleTerminateEvent.php create mode 100644 cacme/vendor/symfony/console/EventListener/ErrorListener.php create mode 100644 cacme/vendor/symfony/console/Exception/CommandNotFoundException.php create mode 100644 cacme/vendor/symfony/console/Exception/ExceptionInterface.php create mode 100644 cacme/vendor/symfony/console/Exception/InvalidArgumentException.php create mode 100644 cacme/vendor/symfony/console/Exception/InvalidOptionException.php create mode 100644 cacme/vendor/symfony/console/Exception/LogicException.php create mode 100644 cacme/vendor/symfony/console/Exception/MissingInputException.php create mode 100644 cacme/vendor/symfony/console/Exception/NamespaceNotFoundException.php create mode 100644 cacme/vendor/symfony/console/Exception/RuntimeException.php create mode 100644 cacme/vendor/symfony/console/Formatter/NullOutputFormatter.php create mode 100644 cacme/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php create mode 100644 cacme/vendor/symfony/console/Formatter/OutputFormatter.php create mode 100644 cacme/vendor/symfony/console/Formatter/OutputFormatterInterface.php create mode 100644 cacme/vendor/symfony/console/Formatter/OutputFormatterStyle.php create mode 100644 cacme/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php create mode 100644 cacme/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php create mode 100644 cacme/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php create mode 100644 cacme/vendor/symfony/console/Helper/DebugFormatterHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/DescriptorHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/Dumper.php create mode 100644 cacme/vendor/symfony/console/Helper/FormatterHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/Helper.php create mode 100644 cacme/vendor/symfony/console/Helper/HelperInterface.php create mode 100644 cacme/vendor/symfony/console/Helper/HelperSet.php create mode 100644 cacme/vendor/symfony/console/Helper/InputAwareHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/ProcessHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/ProgressBar.php create mode 100644 cacme/vendor/symfony/console/Helper/ProgressIndicator.php create mode 100644 cacme/vendor/symfony/console/Helper/QuestionHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/SymfonyQuestionHelper.php create mode 100644 cacme/vendor/symfony/console/Helper/Table.php create mode 100644 cacme/vendor/symfony/console/Helper/TableCell.php create mode 100644 cacme/vendor/symfony/console/Helper/TableCellStyle.php create mode 100644 cacme/vendor/symfony/console/Helper/TableRows.php create mode 100644 cacme/vendor/symfony/console/Helper/TableSeparator.php create mode 100644 cacme/vendor/symfony/console/Helper/TableStyle.php create mode 100644 cacme/vendor/symfony/console/Input/ArgvInput.php create mode 100644 cacme/vendor/symfony/console/Input/ArrayInput.php create mode 100644 cacme/vendor/symfony/console/Input/Input.php create mode 100644 cacme/vendor/symfony/console/Input/InputArgument.php create mode 100644 cacme/vendor/symfony/console/Input/InputAwareInterface.php create mode 100644 cacme/vendor/symfony/console/Input/InputDefinition.php create mode 100644 cacme/vendor/symfony/console/Input/InputInterface.php create mode 100644 cacme/vendor/symfony/console/Input/InputOption.php create mode 100644 cacme/vendor/symfony/console/Input/StreamableInputInterface.php create mode 100644 cacme/vendor/symfony/console/Input/StringInput.php create mode 100644 cacme/vendor/symfony/console/LICENSE create mode 100644 cacme/vendor/symfony/console/Logger/ConsoleLogger.php create mode 100644 cacme/vendor/symfony/console/Output/BufferedOutput.php create mode 100644 cacme/vendor/symfony/console/Output/ConsoleOutput.php create mode 100644 cacme/vendor/symfony/console/Output/ConsoleOutputInterface.php create mode 100644 cacme/vendor/symfony/console/Output/ConsoleSectionOutput.php create mode 100644 cacme/vendor/symfony/console/Output/NullOutput.php create mode 100644 cacme/vendor/symfony/console/Output/Output.php create mode 100644 cacme/vendor/symfony/console/Output/OutputInterface.php create mode 100644 cacme/vendor/symfony/console/Output/StreamOutput.php create mode 100644 cacme/vendor/symfony/console/Output/TrimmedBufferOutput.php create mode 100644 cacme/vendor/symfony/console/Question/ChoiceQuestion.php create mode 100644 cacme/vendor/symfony/console/Question/ConfirmationQuestion.php create mode 100644 cacme/vendor/symfony/console/Question/Question.php create mode 100644 cacme/vendor/symfony/console/README.md create mode 100644 cacme/vendor/symfony/console/Resources/bin/hiddeninput.exe create mode 100644 cacme/vendor/symfony/console/Resources/completion.bash create mode 100644 cacme/vendor/symfony/console/SignalRegistry/SignalRegistry.php create mode 100644 cacme/vendor/symfony/console/SingleCommandApplication.php create mode 100644 cacme/vendor/symfony/console/Style/OutputStyle.php create mode 100644 cacme/vendor/symfony/console/Style/StyleInterface.php create mode 100644 cacme/vendor/symfony/console/Style/SymfonyStyle.php create mode 100644 cacme/vendor/symfony/console/Terminal.php create mode 100644 cacme/vendor/symfony/console/Tester/ApplicationTester.php create mode 100644 cacme/vendor/symfony/console/Tester/CommandCompletionTester.php create mode 100644 cacme/vendor/symfony/console/Tester/CommandTester.php create mode 100644 cacme/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php create mode 100644 cacme/vendor/symfony/console/Tester/TesterTrait.php create mode 100644 cacme/vendor/symfony/console/composer.json create mode 100644 cacme/vendor/symfony/deprecation-contracts/.gitignore create mode 100644 cacme/vendor/symfony/deprecation-contracts/CHANGELOG.md create mode 100644 cacme/vendor/symfony/deprecation-contracts/LICENSE create mode 100644 cacme/vendor/symfony/deprecation-contracts/README.md create mode 100644 cacme/vendor/symfony/deprecation-contracts/composer.json create mode 100644 cacme/vendor/symfony/deprecation-contracts/function.php create mode 100644 cacme/vendor/symfony/polyfill-ctype/Ctype.php create mode 100644 cacme/vendor/symfony/polyfill-ctype/LICENSE create mode 100644 cacme/vendor/symfony/polyfill-ctype/README.md create mode 100644 cacme/vendor/symfony/polyfill-ctype/bootstrap.php create mode 100644 cacme/vendor/symfony/polyfill-ctype/bootstrap80.php create mode 100644 cacme/vendor/symfony/polyfill-ctype/composer.json create mode 100644 cacme/vendor/symfony/polyfill-intl-grapheme/Grapheme.php create mode 100644 cacme/vendor/symfony/polyfill-intl-grapheme/LICENSE create mode 100644 cacme/vendor/symfony/polyfill-intl-grapheme/README.md create mode 100644 cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap.php create mode 100644 cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php create mode 100644 cacme/vendor/symfony/polyfill-intl-grapheme/composer.json create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/LICENSE create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/Normalizer.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/README.md create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php create mode 100644 cacme/vendor/symfony/polyfill-intl-normalizer/composer.json create mode 100644 cacme/vendor/symfony/polyfill-mbstring/LICENSE create mode 100644 cacme/vendor/symfony/polyfill-mbstring/Mbstring.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/README.md create mode 100644 cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/bootstrap.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/bootstrap80.php create mode 100644 cacme/vendor/symfony/polyfill-mbstring/composer.json create mode 100644 cacme/vendor/symfony/service-contracts/.gitignore create mode 100644 cacme/vendor/symfony/service-contracts/Attribute/Required.php create mode 100644 cacme/vendor/symfony/service-contracts/Attribute/SubscribedService.php create mode 100644 cacme/vendor/symfony/service-contracts/CHANGELOG.md create mode 100644 cacme/vendor/symfony/service-contracts/LICENSE create mode 100644 cacme/vendor/symfony/service-contracts/README.md create mode 100644 cacme/vendor/symfony/service-contracts/ResetInterface.php create mode 100644 cacme/vendor/symfony/service-contracts/ServiceLocatorTrait.php create mode 100644 cacme/vendor/symfony/service-contracts/ServiceProviderInterface.php create mode 100644 cacme/vendor/symfony/service-contracts/ServiceSubscriberInterface.php create mode 100644 cacme/vendor/symfony/service-contracts/ServiceSubscriberTrait.php create mode 100644 cacme/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php create mode 100644 cacme/vendor/symfony/service-contracts/composer.json create mode 100644 cacme/vendor/symfony/string/AbstractString.php create mode 100644 cacme/vendor/symfony/string/AbstractUnicodeString.php create mode 100644 cacme/vendor/symfony/string/ByteString.php create mode 100644 cacme/vendor/symfony/string/CHANGELOG.md create mode 100644 cacme/vendor/symfony/string/CodePointString.php create mode 100644 cacme/vendor/symfony/string/Exception/ExceptionInterface.php create mode 100644 cacme/vendor/symfony/string/Exception/InvalidArgumentException.php create mode 100644 cacme/vendor/symfony/string/Exception/RuntimeException.php create mode 100644 cacme/vendor/symfony/string/Inflector/EnglishInflector.php create mode 100644 cacme/vendor/symfony/string/Inflector/FrenchInflector.php create mode 100644 cacme/vendor/symfony/string/Inflector/InflectorInterface.php create mode 100644 cacme/vendor/symfony/string/LICENSE create mode 100644 cacme/vendor/symfony/string/LazyString.php create mode 100644 cacme/vendor/symfony/string/README.md create mode 100644 cacme/vendor/symfony/string/Resources/data/wcswidth_table_wide.php create mode 100644 cacme/vendor/symfony/string/Resources/data/wcswidth_table_zero.php create mode 100644 cacme/vendor/symfony/string/Resources/functions.php create mode 100644 cacme/vendor/symfony/string/Slugger/AsciiSlugger.php create mode 100644 cacme/vendor/symfony/string/Slugger/SluggerInterface.php create mode 100644 cacme/vendor/symfony/string/UnicodeString.php create mode 100644 cacme/vendor/symfony/string/composer.json create mode 100644 cacme/vendor/webman/console/.gitignore create mode 100644 cacme/vendor/webman/console/README.md create mode 100644 cacme/vendor/webman/console/composer.json create mode 100644 cacme/vendor/webman/console/src/Application.php create mode 100644 cacme/vendor/webman/console/src/Command.php create mode 100644 cacme/vendor/webman/console/src/Commands/AppPluginCreateCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/AppPluginInstallCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/AppPluginUninstallCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/BuildBinCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/BuildPharCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/ConnectionsCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/FixDisbaleFunctionsCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/InstallCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/MakeBootstrapCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/MakeCommandCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/MakeControllerCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/MakeMiddlewareCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/MakeModelCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/PluginCreateCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/PluginDisableCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/PluginEnableCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/PluginExportCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/PluginInstallCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/PluginUninstallCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/ReStartCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/ReloadCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/RouteListCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/StartCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/StatusCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/StopCommand.php create mode 100644 cacme/vendor/webman/console/src/Commands/VersionCommand.php create mode 100644 cacme/vendor/webman/console/src/Install.php create mode 100644 cacme/vendor/webman/console/src/Util.php create mode 100644 cacme/vendor/webman/console/src/config/plugin/webman/console/app.php create mode 100755 cacme/vendor/webman/console/src/webman create mode 100644 cacme/vendor/webmozart/assert/CHANGELOG.md create mode 100644 cacme/vendor/webmozart/assert/LICENSE create mode 100644 cacme/vendor/webmozart/assert/README.md create mode 100644 cacme/vendor/webmozart/assert/composer.json create mode 100644 cacme/vendor/webmozart/assert/src/Assert.php create mode 100644 cacme/vendor/webmozart/assert/src/InvalidArgumentException.php create mode 100644 cacme/vendor/webmozart/assert/src/Mixin.php create mode 100644 cacme/vendor/workerman/validation/CHANGELOG.md create mode 100644 cacme/vendor/workerman/validation/CONTRIBUTING.md create mode 100644 cacme/vendor/workerman/validation/LICENSE create mode 100644 cacme/vendor/workerman/validation/README.md create mode 100644 cacme/vendor/workerman/validation/composer.json create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AD.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AERO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AF.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ARPA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AU.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/AZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BB.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BF.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BH.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BJ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/BZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CD.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CK.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CU.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CV.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CX.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/CY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/DM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/DO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/DZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/EC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/EE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/EG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ES.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ET.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/FI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/FJ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/FM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/FR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GD.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GH.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GP.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GU.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/GY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/HK.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/HN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/HR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/HT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/HU.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ID.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/INT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IQ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/IT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/JE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/JO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/JP.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KP.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/KZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LB.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LK.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LV.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/LY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ME.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MK.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ML.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MU.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MV.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MX.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/MZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NF.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/NZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/OM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PF.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PH.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PK.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PRO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/PY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/QA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/RE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/RO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/RS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/RW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SB.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SD.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SH.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ST.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SV.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SX.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/SZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TH.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TJ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TL.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TO.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TR.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TT.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TW.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/TZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/UA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/UG.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/UK.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/US.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/UY.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/UZ.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/VC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/VE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/VI.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/VN.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/VU.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/WS.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/XN--4DBRK0CE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/XN--90A3AC.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/XN--J6W193G.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/XN--O3CW4H.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/YE.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ZA.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ZM.php create mode 100644 cacme/vendor/workerman/validation/data/domain/public-suffix/ZW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AQ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AX.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/AZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BB.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BJ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BQ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BV.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/BZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CV.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CX.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/CZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/DE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/DJ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/DK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/DM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/DO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/DZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/EC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/EE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/EG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/EH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ER.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ES.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ET.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/FI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/FJ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/FK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/FM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/FO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/FR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GB.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GP.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GQ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/GY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/HK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/HM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/HN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/HR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/HT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/HU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ID.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IQ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/IT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/JE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/JM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/JO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/JP.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KP.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/KZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LB.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LV.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/LY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ME.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ML.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MP.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MQ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MV.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MX.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/MZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NP.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/NZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/OM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/PY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/QA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/RE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/RO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/RS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/RU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/RW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SB.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SJ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ST.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SV.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SX.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/SZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TD.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TH.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TJ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TK.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TL.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TO.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TR.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TV.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TW.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/TZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/UA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/UG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/UM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/US.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/UY.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/UZ.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VC.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VG.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VI.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VN.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/VU.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/WF.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/WS.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/YE.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/YT.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ZA.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ZM.php create mode 100644 cacme/vendor/workerman/validation/data/iso_3166-2/ZW.php create mode 100644 cacme/vendor/workerman/validation/library/ChainedValidator.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AllOfException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AlnumException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AlphaException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AlwaysInvalidException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AlwaysValidException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AnyOfException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ArrayTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ArrayValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/AttributeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/Base64Exception.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/BaseException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/BetweenException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/BoolTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/BoolValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/BsnException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CallException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CallableTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CallbackException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CharsetException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CnhException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CnpjException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ComponentException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ConsonantException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ContainsAnyException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ContainsException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ControlException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CountableException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CountryCodeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CpfException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CreditCardException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/CurrencyCodeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/DateException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/DateTimeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/DecimalException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/DigitException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/DirectoryException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/DomainException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/EachException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/EmailException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/EndsWithException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/EqualsException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/EquivalentException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/EvenException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/Exception.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ExecutableException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ExistsException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ExtensionException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FactorException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FalseValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FibonacciException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FileException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FilterVarException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FilteredValidationException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FiniteException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FloatTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/FloatValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/GraphException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/GreaterThanException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/GroupedValidationException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/HexRgbColorException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IbanException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IdenticalException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ImageException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ImeiException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/InException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/InfiniteException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/InstanceException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IntTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IntValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/InvalidClassException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IpException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IsbnException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/IterableTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/JsonException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/KeyException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/KeyNestedException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/KeySetException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/KeyValueException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LanguageCodeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LeapDateException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LeapYearException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LengthException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LessThanException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LowercaseException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/LuhnException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MacAddressException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MaxAgeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MaxException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MimetypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MinAgeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MinException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/MultipleException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NegativeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NestedValidationException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NfeAccessKeyException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NifException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NipException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NoException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NoWhitespaceException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NonOmissibleException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NoneOfException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NotBlankException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NotEmojiException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NotEmptyException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NotException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NotOptionalException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NullTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NullableException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NumberException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/NumericValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ObjectTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/OddException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/OneOfException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/OptionalException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PerfectSquareException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PeselException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PhoneException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PhpLabelException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PisException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PolishIdCardException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PortugueseNifException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PositiveException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PostalCodeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PrimeNumberException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PrintableException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PublicDomainSuffixException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/PunctException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ReadableException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/RecursiveExceptionIterator.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/RegexException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ResourceTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/RomanException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ScalarValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SfException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SizeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SlugException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SortedException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SpaceException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/StartsWithException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/StringTypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/StringValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SubdivisionCodeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SubsetException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/SymbolicLinkException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/TimeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/TldException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/TrueValException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/TypeException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/UniqueException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/UploadedException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/UppercaseException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/UrlException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/UuidException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ValidationException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/ValidatorException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/VersionException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/VideoUrlException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/VowelException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/WhenException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/WritableException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/XdigitException.php create mode 100644 cacme/vendor/workerman/validation/library/Exceptions/YesException.php create mode 100644 cacme/vendor/workerman/validation/library/Factory.php create mode 100644 cacme/vendor/workerman/validation/library/Helpers/CanCompareValues.php create mode 100644 cacme/vendor/workerman/validation/library/Helpers/CanValidateDateTime.php create mode 100644 cacme/vendor/workerman/validation/library/Helpers/CanValidateIterable.php create mode 100644 cacme/vendor/workerman/validation/library/Helpers/CanValidateUndefined.php create mode 100644 cacme/vendor/workerman/validation/library/Helpers/CountryInfo.php create mode 100644 cacme/vendor/workerman/validation/library/Helpers/DomainInfo.php create mode 100644 cacme/vendor/workerman/validation/library/Message/Formatter.php create mode 100644 cacme/vendor/workerman/validation/library/Message/ParameterStringifier.php create mode 100644 cacme/vendor/workerman/validation/library/Message/Stringifier/KeepOriginalStringName.php create mode 100644 cacme/vendor/workerman/validation/library/NonNegatable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractAge.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractComparison.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractComposite.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractEnvelope.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractFilterRule.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractRelated.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractRule.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractSearcher.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AbstractWrapper.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AllOf.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Alnum.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Alpha.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AlwaysInvalid.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AlwaysValid.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/AnyOf.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/ArrayType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/ArrayVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Attribute.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Base.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Base64.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Between.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/BoolType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/BoolVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Bsn.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Call.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/CallableType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Callback.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Charset.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Cnh.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Cnpj.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Consonant.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Contains.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/ContainsAny.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Control.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Countable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/CountryCode.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Cpf.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/CreditCard.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/CurrencyCode.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Date.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/DateTime.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Decimal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Digit.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Directory.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Domain.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Each.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Email.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/EndsWith.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Equals.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Equivalent.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Even.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Executable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Exists.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Extension.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Factor.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/FalseVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Fibonacci.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/File.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/FilterVar.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Finite.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/FloatType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/FloatVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Graph.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/GreaterThan.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/HexRgbColor.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Iban.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Identical.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Image.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Imei.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/In.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Infinite.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Instance.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/IntType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/IntVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Ip.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Isbn.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/IterableType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Json.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Key.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/KeyNested.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/KeySet.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/KeyValue.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/LanguageCode.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/LeapDate.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/LeapYear.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Length.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/LessThan.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Lowercase.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Luhn.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/MacAddress.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Max.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/MaxAge.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Mimetype.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Min.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/MinAge.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Mobile.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Multiple.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Negative.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NfeAccessKey.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Nif.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Nip.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/No.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NoWhitespace.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NoneOf.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Not.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NotBlank.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NotEmoji.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NotEmpty.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NotOptional.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NullType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Nullable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Number.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/NumericVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/ObjectType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Odd.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/OneOf.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Optional.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PerfectSquare.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Pesel.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Phone.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PhpLabel.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Pis.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PolishIdCard.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PortugueseNif.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Positive.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PostalCode.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PrimeNumber.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Printable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/PublicDomainSuffix.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Punct.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Readable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Regex.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/ResourceType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Roman.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/ScalarVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Size.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Slug.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Sorted.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Space.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/StartsWith.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/StringType.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/StringVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/SubdivisionCode.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Subset.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/SymbolicLink.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Time.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Tld.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/TrueVal.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Type.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Unique.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Uploaded.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Uppercase.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Url.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Uuid.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Version.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/VideoUrl.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Vowel.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/When.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Writable.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Xdigit.php create mode 100644 cacme/vendor/workerman/validation/library/Rules/Yes.php create mode 100644 cacme/vendor/workerman/validation/library/StaticValidator.php create mode 100644 cacme/vendor/workerman/validation/library/Validatable.php create mode 100644 cacme/vendor/workerman/validation/library/Validator.php create mode 100644 cacme/vendor/workerman/webman-framework/.gitignore create mode 100644 cacme/vendor/workerman/webman-framework/README.md create mode 100644 cacme/vendor/workerman/webman-framework/composer.json create mode 100644 cacme/vendor/workerman/webman-framework/src/App.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Bootstrap.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Config.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Container.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Context.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandler.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandlerInterface.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Exception/FileException.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Exception/NotFoundException.php create mode 100644 cacme/vendor/workerman/webman-framework/src/File.php create mode 100644 cacme/vendor/workerman/webman-framework/src/FileSessionHandler.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Http/Request.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Http/Response.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Http/UploadFile.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Install.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Middleware.php create mode 100644 cacme/vendor/workerman/webman-framework/src/MiddlewareInterface.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Route.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Route/Route.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Session/FileSessionHandler.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Session/RedisClusterSessionHandler.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Session/RedisSessionHandler.php create mode 100644 cacme/vendor/workerman/webman-framework/src/Util.php create mode 100644 cacme/vendor/workerman/webman-framework/src/View.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/App.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Cache.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Container.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Context.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Db.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Log.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Model.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Plugin.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Redis.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Request.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Response.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/Translation.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/View.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/bootstrap/LaravelDb.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/bootstrap/Session.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/exception/BusinessException.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/exception/Handler.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/view/Blade.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/view/Raw.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/view/ThinkPHP.php create mode 100644 cacme/vendor/workerman/webman-framework/src/support/view/Twig.php create mode 100644 cacme/vendor/workerman/workerman/.github/FUNDING.yml create mode 100644 cacme/vendor/workerman/workerman/.gitignore create mode 100644 cacme/vendor/workerman/workerman/Autoloader.php create mode 100644 cacme/vendor/workerman/workerman/Connection/AsyncTcpConnection.php create mode 100644 cacme/vendor/workerman/workerman/Connection/AsyncUdpConnection.php create mode 100644 cacme/vendor/workerman/workerman/Connection/ConnectionInterface.php create mode 100644 cacme/vendor/workerman/workerman/Connection/TcpConnection.php create mode 100644 cacme/vendor/workerman/workerman/Connection/UdpConnection.php create mode 100644 cacme/vendor/workerman/workerman/Events/Ev.php create mode 100644 cacme/vendor/workerman/workerman/Events/Event.php create mode 100644 cacme/vendor/workerman/workerman/Events/EventInterface.php create mode 100644 cacme/vendor/workerman/workerman/Events/Libevent.php create mode 100644 cacme/vendor/workerman/workerman/Events/React/Base.php create mode 100644 cacme/vendor/workerman/workerman/Events/React/ExtEventLoop.php create mode 100644 cacme/vendor/workerman/workerman/Events/React/ExtLibEventLoop.php create mode 100644 cacme/vendor/workerman/workerman/Events/React/StreamSelectLoop.php create mode 100644 cacme/vendor/workerman/workerman/Events/Select.php create mode 100644 cacme/vendor/workerman/workerman/Events/Swoole.php create mode 100644 cacme/vendor/workerman/workerman/Events/Uv.php create mode 100644 cacme/vendor/workerman/workerman/Lib/Constants.php create mode 100644 cacme/vendor/workerman/workerman/Lib/Timer.php create mode 100644 cacme/vendor/workerman/workerman/MIT-LICENSE.txt create mode 100644 cacme/vendor/workerman/workerman/Protocols/Frame.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Chunk.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Request.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Response.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/ServerSentEvents.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Session.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Session/FileSessionHandler.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisClusterSessionHandler.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisSessionHandler.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/Session/SessionHandlerInterface.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Http/mime.types create mode 100644 cacme/vendor/workerman/workerman/Protocols/ProtocolInterface.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Text.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Websocket.php create mode 100644 cacme/vendor/workerman/workerman/Protocols/Ws.php create mode 100644 cacme/vendor/workerman/workerman/README.md create mode 100644 cacme/vendor/workerman/workerman/Timer.php create mode 100644 cacme/vendor/workerman/workerman/Worker.php create mode 100644 cacme/vendor/workerman/workerman/composer.json create mode 100644 cacme/vendor/yzh52521/easyhttp/LICENSE create mode 100644 cacme/vendor/yzh52521/easyhttp/README.md create mode 100644 cacme/vendor/yzh52521/easyhttp/composer.json create mode 100644 cacme/vendor/yzh52521/easyhttp/src/ConnectionException.php create mode 100755 cacme/vendor/yzh52521/easyhttp/src/Facade.php create mode 100644 cacme/vendor/yzh52521/easyhttp/src/Http.php create mode 100644 cacme/vendor/yzh52521/easyhttp/src/Logger.php create mode 100644 cacme/vendor/yzh52521/easyhttp/src/Request.php create mode 100644 cacme/vendor/yzh52521/easyhttp/src/RequestException.php create mode 100644 cacme/vendor/yzh52521/easyhttp/src/Response.php create mode 100644 cacme/vendor/yzh52521/easyhttp/src/Retry.php create mode 100755 cacme/webman create mode 100644 cacme/windows.bat create mode 100644 cacme/windows.php create mode 100644 index.html create mode 100644 xb.php diff --git a/404.html b/404.html new file mode 100644 index 0000000..d728009 --- /dev/null +++ b/404.html @@ -0,0 +1 @@ +别急,还没弄好 \ No newline at end of file diff --git a/acme b/acme new file mode 160000 index 0000000..452d755 --- /dev/null +++ b/acme @@ -0,0 +1 @@ +Subproject commit 452d755719e53231601212b60ebb2e0855a857c3 diff --git a/acme.sh b/acme.sh new file mode 100644 index 0000000..e69de29 diff --git a/cacme/.gitignore b/cacme/.gitignore new file mode 100644 index 0000000..5e3fc9c --- /dev/null +++ b/cacme/.gitignore @@ -0,0 +1 @@ +./keys/* \ No newline at end of file diff --git a/cacme/LICENSE b/cacme/LICENSE new file mode 100644 index 0000000..2c66292 --- /dev/null +++ b/cacme/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 walkor and contributors (see https://github.com/walkor/webman/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/cacme/README.md b/cacme/README.md new file mode 100644 index 0000000..6d1caf2 --- /dev/null +++ b/cacme/README.md @@ -0,0 +1,4 @@ +# PHP ACME Cli in Webman + +run: +php webman acme \ No newline at end of file diff --git a/cacme/app/command/Acme.php b/cacme/app/command/Acme.php new file mode 100644 index 0000000..c8b350e --- /dev/null +++ b/cacme/app/command/Acme.php @@ -0,0 +1,133 @@ +addArgument('name', InputArgument::OPTIONAL, 'Name description'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $EMAIL='youremail@yourdomain.com'; + $DOMAIN='yourdomain.com'; + #$CA='https://acme-v02.api.letsencrypt.org/directory'; + $CA='https://acme-staging-v02.api.letsencrypt.org/directory'; + $secureHttpClientFactory = new SecureHttpClientFactory( + new GuzzleHttpClient(), + new Base64SafeEncoder(), + new KeyParser(), + new DataSigner(), + new ServerErrorHandler() + ); + + $publicKeyPath = base_path().'/keys/account.pub.pem'; + $privateKeyPath = base_path().'/keys/account.pem'; + + if (!file_exists($privateKeyPath)) { + $keyPairGenerator = new KeyPairGenerator(); + $keyPair = $keyPairGenerator->generateKeyPair(); + + file_put_contents($publicKeyPath, $keyPair->getPublicKey()->getPEM()); + file_put_contents($privateKeyPath, $keyPair->getPrivateKey()->getPEM()); + } else { + $publicKey = new PublicKey(file_get_contents($publicKeyPath)); + $privateKey = new PrivateKey(file_get_contents($privateKeyPath)); + + $keyPair = new KeyPair($publicKey, $privateKey); + } + $secureHttpClient = $secureHttpClientFactory->createSecureHttpClient($keyPair); + + #$acmeClient = new AcmeClient($secureHttpClient, 'https://acme-v02.api.letsencrypt.org/directory'); + $acmeClient = new AcmeClient($secureHttpClient, $CA); + + $acmeClient->registerAccount($EMAIL,null); + + $authorizationChallenges = $acmeClient->requestAuthorization($DOMAIN); + + foreach($authorizationChallenges as $id=>$cha){ + + $cha->id=$id; + $dde=new DnsDataExtractor; + $cha->value=$dde->getRecordValue($cha); + print_r($cha); + } + #print_r($authorizationChallenges); + + + #print_r($dde->getRecordValue($authorizationChallenges[1])); + + #$output->writeln($authorizationChallenges); + + $helper = $this->getHelper('question'); + $question = new ChoiceQuestion( + '选择对应的ID', + array('0', '1', '2'), + 0 + ); + $way = $helper->ask($input, $output, $question); + + $acmeClient->challengeAuthorization($authorizationChallenges[$way]); + + $dn = new DistinguishedName($DOMAIN); + + $keyPairGenerator = new KeyPairGenerator(); + + // Make a new key pair. We'll keep the private key as our cert key + $domainKeyPair = $keyPairGenerator->generateKeyPair(); + + // This is the private key + var_dump($domainKeyPair->getPrivateKey()->getPem()); + + // Generate CSR + $csr = new CertificateRequest($dn, $domainKeyPair); + + $certificateResponse = $acmeClient->requestCertificate($DOMAIN, $csr); + + // This is the certificate (public key) + var_dump($certificateResponse->getCertificate()->getPem()); + + // For Let's Encrypt, you will need the intermediate too + var_dump($certificateResponse->getCertificate()->getIssuerCertificate()->getPEM()); + + return self::SUCCESS; + } + +} diff --git a/cacme/app/controller/Apply.php b/cacme/app/controller/Apply.php new file mode 100644 index 0000000..a956ccb --- /dev/null +++ b/cacme/app/controller/Apply.php @@ -0,0 +1,27 @@ +input('email',null); + $domain=$request->input('domain',null); + $cert=$request->input('cert',null); + if(!$email||!$domain||!$cert){ + return json(['code'=>404,'msg'=>'缺少参数,请刷新重试']); + } + if(!in_array($cert,array('R3','Laysense','FWNET'))){ + return json(['code'=>404,'msg'=>'证书类型错误或不存在']); + } + if(in_array($cert,array('Laysense','FWNET'))){ + return json(['code'=>403,'msg'=>'当前证书类型'.$cert.'暂时无法颁发']); + } + if(!v::domain($innerDomain)->validate($domain)) + return view('index'); + } +} diff --git a/cacme/app/controller/IndexController.php b/cacme/app/controller/IndexController.php new file mode 100644 index 0000000..f6898eb --- /dev/null +++ b/cacme/app/controller/IndexController.php @@ -0,0 +1,13 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace app\middleware; + +use Webman\MiddlewareInterface; +use Webman\Http\Response; +use Webman\Http\Request; + +/** + * Class StaticFile + * @package app\middleware + */ +class StaticFile implements MiddlewareInterface +{ + public function process(Request $request, callable $next): Response + { + // Access to files beginning with. Is prohibited + if (strpos($request->path(), '/.') !== false) { + return response('

403 forbidden

', 403); + } + /** @var Response $response */ + $response = $next($request); + // Add cross domain HTTP header + /*$response->withHeaders([ + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Credentials' => 'true', + ]);*/ + return $response; + } +} diff --git a/cacme/app/model/Test.php b/cacme/app/model/Test.php new file mode 100644 index 0000000..92d70e3 --- /dev/null +++ b/cacme/app/model/Test.php @@ -0,0 +1,29 @@ + + + + + + + + Center ACME Auto SSL + + + + + + +
+

+ Center ACME Auto SSL(CAAS) by Laysense +

+

[由 来笙实验室 出品]

+
+

CAAS将打破你对ssl和acme的认识,现在只需要设置一次302重定向就可以直接申请到证书辣!

+
+ + + + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/cacme/composer.json b/cacme/composer.json new file mode 100644 index 0000000..b185359 --- /dev/null +++ b/cacme/composer.json @@ -0,0 +1,60 @@ +{ + "name": "workerman/webman", + "type": "project", + "keywords": [ + "high performance", + "http service" + ], + "homepage": "https://www.workerman.net", + "license": "MIT", + "description": "High performance HTTP Service Framework.", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/walkor/webman/issues", + "forum": "https://wenda.workerman.net/", + "wiki": "https://workerman.net/doc/webman", + "source": "https://github.com/walkor/webman" + }, + "require": { + "php": ">=7.2", + "workerman/webman-framework": "^1.5.0", + "monolog/monolog": "^2.0", + "webman/console": "^1.3", + "acmephp/core": "^2.1", + "yzh52521/easyhttp": "^1.1", + "workerman/validation": "^3.1" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "autoload": { + "psr-4": { + "": "./", + "app\\": "./app", + "App\\": "./app", + "app\\View\\Components\\": "./app/view/components" + }, + "files": [ + "./support/helpers.php" + ] + }, + "scripts": { + "post-package-install": [ + "support\\Plugin::install" + ], + "post-package-update": [ + "support\\Plugin::install" + ], + "pre-package-uninstall": [ + "support\\Plugin::uninstall" + ] + } +} diff --git a/cacme/composer.lock b/cacme/composer.lock new file mode 100644 index 0000000..40af94e --- /dev/null +++ b/cacme/composer.lock @@ -0,0 +1,2516 @@ +{ + "_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": "8bb1181a1089647f645ccc37c9d8d46c", + "packages": [ + { + "name": "acmephp/core", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/acmephp/core.git", + "reference": "ca7f26e27e4c14fbf90f7c117302fb2ae38576d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/acmephp/core/zipball/ca7f26e27e4c14fbf90f7c117302fb2ae38576d7", + "reference": "ca7f26e27e4c14fbf90f7c117302fb2ae38576d7", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "acmephp/ssl": "^2.0", + "ext-hash": "*", + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "guzzlehttp/psr7": "^1.7|^2.1", + "lcobucci/jwt": "^3.3|^4.0", + "php": ">=7.2.5", + "psr/http-message": "^1.0", + "psr/log": "^1.0|^2.0|^3.0", + "webmozart/assert": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AcmePhp\\Core\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Titouan Galopin", + "email": "galopintitouan@gmail.com", + "homepage": "http://titouangalopin.com" + }, + { + "name": "Jérémy Derussé", + "homepage": "https://twitter.com/jderusse" + } + ], + "description": "Raw implementation of the ACME protocol in PHP", + "homepage": "https://github.com/acmephp/core", + "keywords": [ + "acmephp", + "certificate", + "csr", + "encryption", + "https", + "letsencrypt", + "openssl", + "ssl", + "x509" + ], + "support": { + "source": "https://github.com/acmephp/core/tree/2.1.0" + }, + "time": "2022-05-31T17:36:40+00:00" + }, + { + "name": "acmephp/ssl", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/acmephp/ssl.git", + "reference": "c78ad953d3680acf3f02024c93ff32724d353590" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/acmephp/ssl/zipball/c78ad953d3680acf3f02024c93ff32724d353590", + "reference": "c78ad953d3680acf3f02024c93ff32724d353590", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-hash": "*", + "ext-openssl": "*", + "lib-openssl": ">=0.9.8", + "php": ">=7.2.5", + "webmozart/assert": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AcmePhp\\Ssl\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Titouan Galopin", + "email": "galopintitouan@gmail.com", + "homepage": "http://titouangalopin.com" + }, + { + "name": "Jérémy Derussé", + "homepage": "https://twitter.com/jderusse" + } + ], + "description": "PHP wrapper around OpenSSL extension providing SSL encoding, decoding, parsing and signing features", + "homepage": "https://github.com/acmephp/ssl", + "keywords": [ + "ECDSA", + "acmephp", + "certificate", + "csr", + "https", + "openssl", + "rsa", + "ssl", + "x509" + ], + "support": { + "issues": "https://github.com/acmephp/ssl/issues", + "source": "https://github.com/acmephp/ssl/tree/2.1.0" + }, + "time": "2022-05-31T16:44:35+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "lcobucci/clock", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/clock.git", + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/fb533e093fd61321bfcbac08b131ce805fe183d3", + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0", + "stella-maris/clock": "^0.1.4" + }, + "require-dev": { + "infection/infection": "^0.26", + "lcobucci/coding-standard": "^8.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com" + } + ], + "description": "Yet another clock abstraction", + "support": { + "issues": "https://github.com/lcobucci/clock/issues", + "source": "https://github.com/lcobucci/clock/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2022-04-19T19:34:17+00:00" + }, + { + "name": "lcobucci/jwt", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/4d7de2fe0d51a96418c0d04004986e410e87f6b4", + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-hash": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-sodium": "*", + "lcobucci/clock": "^2.0 || ^3.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "infection/infection": "^0.21", + "lcobucci/coding-standard": "^6.0", + "mikey179/vfsstream": "^1.6.7", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/php-invoker": "^3.1", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "support": { + "issues": "https://github.com/lcobucci/jwt/issues", + "source": "https://github.com/lcobucci/jwt/tree/4.3.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2023-01-02T13:28:00+00:00" + }, + { + "name": "monolog/monolog", + "version": "2.9.2", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", + "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.9.2" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2023-10-27T15:25:26+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "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": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "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" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "time": "2023-04-04T09:50:52+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "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.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "respect/stringifier", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/Respect/Stringifier.git", + "reference": "e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Respect/Stringifier/zipball/e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59", + "reference": "e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.8", + "malukenho/docheader": "^0.1.7", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/stringify.php" + ], + "psr-4": { + "Respect\\Stringifier\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Respect/Stringifier Contributors", + "homepage": "https://github.com/Respect/Stringifier/graphs/contributors" + } + ], + "description": "Converts any value to a string", + "homepage": "http://respect.github.io/Stringifier/", + "keywords": [ + "respect", + "stringifier", + "stringify" + ], + "support": { + "issues": "https://github.com/Respect/Stringifier/issues", + "source": "https://github.com/Respect/Stringifier/tree/0.2.0" + }, + "time": "2017-12-29T19:39:25+00:00" + }, + { + "name": "stella-maris/clock", + "version": "0.1.7", + "source": { + "type": "git", + "url": "https://github.com/stella-maris-solutions/clock.git", + "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stella-maris-solutions/clock/zipball/fa23ce16019289a18bb3446fdecd45befcdd94f8", + "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0|^8.0", + "psr/clock": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "StellaMaris\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Heigl", + "role": "Maintainer" + } + ], + "description": "A pre-release of the proposed PSR-20 Clock-Interface", + "homepage": "https://gitlab.com/stella-maris/clock", + "keywords": [ + "clock", + "datetime", + "point in time", + "psr20" + ], + "support": { + "source": "https://github.com/stella-maris-solutions/clock/tree/0.1.7" + }, + "time": "2022-11-25T16:15:06+00:00" + }, + { + "name": "symfony/console", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-01T08:36:10+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:55:41+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-28T09:04:16+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-30T19:17:58+00:00" + }, + { + "name": "symfony/string", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-01T08:36:10+00:00" + }, + { + "name": "webman/console", + "version": "v1.3.4", + "source": { + "type": "git", + "url": "https://github.com/webman-php/console.git", + "reference": "ee50a1eca292eea5bf70661aa2ef722e1294814c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webman-php/console/zipball/ee50a1eca292eea5bf70661aa2ef722e1294814c", + "reference": "ee50a1eca292eea5bf70661aa2ef722e1294814c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "doctrine/inflector": "^2.0", + "symfony/console": ">=5.0" + }, + "require-dev": { + "workerman/webman": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\Console\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "description": "Webman console", + "homepage": "http://www.workerman.net", + "keywords": [ + "webman console" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "http://www.workerman.net/questions", + "issues": "https://github.com/webman-php/console/issues", + "source": "https://github.com/webman-php/console", + "wiki": "http://www.workerman.net/doc/webman" + }, + "time": "2024-01-23T03:25:23+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "workerman/validation", + "version": "v3.1.2", + "source": { + "type": "git", + "url": "https://github.com/walkor/validation.git", + "reference": "a4e9896e76b2fac92aff9a9f784df55f615571a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/validation/zipball/a4e9896e76b2fac92aff9a9f784df55f615571a0", + "reference": "a4e9896e76b2fac92aff9a9f784df55f615571a0", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^8.0 || ^8.1 || ^8.2", + "respect/stringifier": "^0.2.0", + "symfony/polyfill-mbstring": "^1.2" + }, + "require-dev": { + "egulias/email-validator": "^3.0", + "giggsey/libphonenumber-for-php-lite": "^8.13", + "malukenho/docheader": "^1.0", + "mikey179/vfsstream": "^1.6", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.6", + "psr/http-message": "^1.0", + "respect/coding-standard": "^3.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "suggest": { + "egulias/email-validator": "Improves the Email rule if available", + "ext-bcmath": "Arbitrary Precision Mathematics", + "ext-fileinfo": "File Information", + "ext-mbstring": "Multibyte String Functions", + "giggsey/libphonenumber-for-php-lite": "Enables the phone rule if available" + }, + "type": "library", + "autoload": { + "psr-4": { + "Respect\\Validation\\": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Respect/Validation Contributors", + "homepage": "https://github.com/Respect/Validation/graphs/contributors" + } + ], + "description": "The most awesome validation engine ever created for PHP. Respect/Validation 汉化版本", + "homepage": "http://respect.github.io/Validation/", + "keywords": [ + "respect", + "validation", + "validator" + ], + "support": { + "source": "https://github.com/walkor/validation/tree/v3.1.2" + }, + "time": "2023-12-07T06:19:04+00:00" + }, + { + "name": "workerman/webman-framework", + "version": "v1.5.16", + "source": { + "type": "git", + "url": "https://github.com/walkor/webman-framework.git", + "reference": "84335520a340ee60adf7cf17aeb0edb9536c24e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/webman-framework/zipball/84335520a340ee60adf7cf17aeb0edb9536c24e8", + "reference": "84335520a340ee60adf7cf17aeb0edb9536c24e8", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": ">=7.2", + "psr/container": ">=1.0", + "workerman/workerman": "^4.0.4 || ^5.0.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\": "./src", + "Support\\": "./src/support", + "support\\": "./src/support", + "Support\\View\\": "./src/support/view", + "Support\\Bootstrap\\": "./src/support/bootstrap", + "Support\\Exception\\": "./src/support/exception" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "description": "High performance HTTP Service Framework.", + "homepage": "https://www.workerman.net", + "keywords": [ + "High Performance", + "http service" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "https://wenda.workerman.net/", + "issues": "https://github.com/walkor/webman/issues", + "source": "https://github.com/walkor/webman-framework", + "wiki": "https://doc.workerman.net/" + }, + "time": "2024-01-15T12:11:49+00:00" + }, + { + "name": "workerman/workerman", + "version": "v4.1.15", + "source": { + "type": "git", + "url": "https://github.com/walkor/workerman.git", + "reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/workerman/zipball/afc8242fc769ab7cf22eb4ac22b97cb59d465e4e", + "reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "type": "library", + "autoload": { + "psr-4": { + "Workerman\\": "./" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", + "homepage": "http://www.workerman.net", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "http://wenda.workerman.net/", + "issues": "https://github.com/walkor/workerman/issues", + "source": "https://github.com/walkor/workerman", + "wiki": "http://doc.workerman.net/" + }, + "funding": [ + { + "url": "https://opencollective.com/workerman", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/walkor", + "type": "patreon" + } + ], + "time": "2024-02-19T02:10:39+00:00" + }, + { + "name": "yzh52521/easyhttp", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/yuanzhihai/easyhttp.git", + "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yuanzhihai/easyhttp/zipball/02bcf47eaf723520fa3905d0e6f1852168fe646c", + "reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "guzzlehttp/guzzle": "^6.0|^7.0", + "php": ">=7.2.5", + "psr/log": "^1.0|^2.0|^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "yzh52521\\EasyHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "yzh52521", + "email": "396751927@qq.com" + } + ], + "description": "EasyHttp 是一个轻量级、语义化、对IDE友好的HTTP客户端,支持常见的HTTP请求、异步请求和并发请求,让你可以快速地使用 HTTP 请求与其他 Web 应用进行通信。", + "homepage": "https://github.com/yzh52521/easyhttp", + "keywords": [ + "EasyHttp", + "curl", + "easy-http", + "http", + "php", + "php-http", + "phphttp" + ], + "support": { + "issues": "https://github.com/yuanzhihai/easyhttp/issues", + "source": "https://github.com/yuanzhihai/easyhttp/tree/v1.1.3" + }, + "time": "2023-11-14T05:49:02+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.2" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/cacme/config/app.php b/cacme/config/app.php new file mode 100644 index 0000000..f26e358 --- /dev/null +++ b/cacme/config/app.php @@ -0,0 +1,26 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\Request; + +return [ + 'debug' => true, + 'error_reporting' => E_ALL, + 'default_timezone' => 'Asia/Shanghai', + 'request_class' => Request::class, + 'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public', + 'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime', + 'controller_suffix' => 'Controller', + 'controller_reuse' => false, +]; diff --git a/cacme/config/autoload.php b/cacme/config/autoload.php new file mode 100644 index 0000000..69a8135 --- /dev/null +++ b/cacme/config/autoload.php @@ -0,0 +1,21 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'files' => [ + base_path() . '/app/functions.php', + base_path() . '/support/Request.php', + base_path() . '/support/Response.php', + ] +]; diff --git a/cacme/config/bootstrap.php b/cacme/config/bootstrap.php new file mode 100644 index 0000000..44054e0 --- /dev/null +++ b/cacme/config/bootstrap.php @@ -0,0 +1,18 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + support\bootstrap\Session::class, + support\bootstrap\LaravelDb::class, +]; diff --git a/cacme/config/container.php b/cacme/config/container.php new file mode 100644 index 0000000..106b7b4 --- /dev/null +++ b/cacme/config/container.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return new Webman\Container; \ No newline at end of file diff --git a/cacme/config/database.php b/cacme/config/database.php new file mode 100644 index 0000000..7dc463a --- /dev/null +++ b/cacme/config/database.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; diff --git a/cacme/config/dependence.php b/cacme/config/dependence.php new file mode 100644 index 0000000..8e964ed --- /dev/null +++ b/cacme/config/dependence.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; \ No newline at end of file diff --git a/cacme/config/exception.php b/cacme/config/exception.php new file mode 100644 index 0000000..f2aede3 --- /dev/null +++ b/cacme/config/exception.php @@ -0,0 +1,17 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + '' => support\exception\Handler::class, +]; \ No newline at end of file diff --git a/cacme/config/log.php b/cacme/config/log.php new file mode 100644 index 0000000..7f05de5 --- /dev/null +++ b/cacme/config/log.php @@ -0,0 +1,32 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'handlers' => [ + [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + runtime_path() . '/logs/webman.log', + 7, //$maxFiles + Monolog\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ] + ], + ], +]; diff --git a/cacme/config/middleware.php b/cacme/config/middleware.php new file mode 100644 index 0000000..8e964ed --- /dev/null +++ b/cacme/config/middleware.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; \ No newline at end of file diff --git a/cacme/config/plugin/webman/console/app.php b/cacme/config/plugin/webman/console/app.php new file mode 100644 index 0000000..074e986 --- /dev/null +++ b/cacme/config/plugin/webman/console/app.php @@ -0,0 +1,24 @@ + true, + + 'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build', + + 'phar_filename' => 'webman.phar', + + 'bin_filename' => 'webman.bin', + + 'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL. + + 'private_key_file' => '', // The file path for certificate or OpenSSL private key file. + + 'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#', + + 'exclude_files' => [ + '.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin' + ], + + 'custom_ini' => ' +memory_limit = 256M + ', +]; diff --git a/cacme/config/process.php b/cacme/config/process.php new file mode 100644 index 0000000..f94d27f --- /dev/null +++ b/cacme/config/process.php @@ -0,0 +1,42 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +global $argv; + +return [ + // File update detection and automatic reload + 'monitor' => [ + 'handler' => process\Monitor::class, + 'reloadable' => false, + 'constructor' => [ + // Monitor these directories + 'monitorDir' => array_merge([ + app_path(), + config_path(), + base_path() . '/process', + base_path() . '/support', + base_path() . '/resource', + base_path() . '/.env', + ], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')), + // Files with these suffixes will be monitored + 'monitorExtensions' => [ + 'php', 'html', 'htm', 'env' + ], + 'options' => [ + 'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/', + 'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/', + ] + ] + ] +]; diff --git a/cacme/config/redis.php b/cacme/config/redis.php new file mode 100644 index 0000000..2f9757a --- /dev/null +++ b/cacme/config/redis.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'database' => 0, + ], +]; diff --git a/cacme/config/route.php b/cacme/config/route.php new file mode 100644 index 0000000..23835fa --- /dev/null +++ b/cacme/config/route.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Webman\Route; +Route::any('/apply/check', [app\controller\Apply::class, 'check']); + + + + + + diff --git a/cacme/config/server.php b/cacme/config/server.php new file mode 100644 index 0000000..f1871c0 --- /dev/null +++ b/cacme/config/server.php @@ -0,0 +1,31 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'listen' => 'http://0.0.0.0:9961', + 'transport' => 'tcp', + 'context' => [], + 'name' => 'webman', + 'count' => cpu_count() * 4, + 'user' => '', + 'group' => '', + 'reusePort' => false, + 'event_loop' => '', + 'stop_timeout' => 2, + 'pid_file' => runtime_path() . '/webman.pid', + 'status_file' => runtime_path() . '/webman.status', + 'stdout_file' => runtime_path() . '/logs/stdout.log', + 'log_file' => runtime_path() . '/logs/workerman.log', + 'max_package_size' => 10 * 1024 * 1024 +]; diff --git a/cacme/config/session.php b/cacme/config/session.php new file mode 100644 index 0000000..043f8c4 --- /dev/null +++ b/cacme/config/session.php @@ -0,0 +1,65 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Webman\Session\FileSessionHandler; +use Webman\Session\RedisSessionHandler; +use Webman\Session\RedisClusterSessionHandler; + +return [ + + 'type' => 'file', // or redis or redis_cluster + + 'handler' => FileSessionHandler::class, + + 'config' => [ + 'file' => [ + 'save_path' => runtime_path() . '/sessions', + ], + 'redis' => [ + 'host' => '127.0.0.1', + 'port' => 6379, + 'auth' => '', + 'timeout' => 2, + 'database' => '', + 'prefix' => 'redis_session_', + ], + 'redis_cluster' => [ + 'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'], + 'timeout' => 2, + 'auth' => '', + 'prefix' => 'redis_session_', + ] + ], + + 'session_name' => 'PHPSID', + + 'auto_update_timestamp' => false, + + 'lifetime' => 7*24*60*60, + + 'cookie_lifetime' => 365*24*60*60, + + 'cookie_path' => '/', + + 'domain' => '', + + 'http_only' => true, + + 'secure' => false, + + 'same_site' => '', + + 'gc_probability' => [1, 1000], + +]; diff --git a/cacme/config/static.php b/cacme/config/static.php new file mode 100644 index 0000000..2f76cf3 --- /dev/null +++ b/cacme/config/static.php @@ -0,0 +1,23 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Static file settings + */ +return [ + 'enable' => true, + 'middleware' => [ // Static file Middleware + //app\middleware\StaticFile::class, + ], +]; \ No newline at end of file diff --git a/cacme/config/translation.php b/cacme/config/translation.php new file mode 100644 index 0000000..96589b2 --- /dev/null +++ b/cacme/config/translation.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Multilingual configuration + */ +return [ + // Default language + 'locale' => 'zh_CN', + // Fallback language + 'fallback_locale' => ['zh_CN', 'en'], + // Folder where language files are stored + 'path' => base_path() . '/resource/translations', +]; \ No newline at end of file diff --git a/cacme/config/view.php b/cacme/config/view.php new file mode 100644 index 0000000..e3a7b85 --- /dev/null +++ b/cacme/config/view.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\view\Raw; +use support\view\Twig; +use support\view\Blade; +use support\view\ThinkPHP; + +return [ + 'handler' => Raw::class +]; diff --git a/cacme/process/Monitor.php b/cacme/process/Monitor.php new file mode 100644 index 0000000..92b3716 --- /dev/null +++ b/cacme/process/Monitor.php @@ -0,0 +1,243 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace process; + +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use SplFileInfo; +use Workerman\Timer; +use Workerman\Worker; + +/** + * Class FileMonitor + * @package process + */ +class Monitor +{ + /** + * @var array + */ + protected $paths = []; + + /** + * @var array + */ + protected $extensions = []; + + /** + * @var string + */ + public static $lockFile = __DIR__ . '/../runtime/monitor.lock'; + + /** + * Pause monitor + * @return void + */ + public static function pause() + { + file_put_contents(static::$lockFile, time()); + } + + /** + * Resume monitor + * @return void + */ + public static function resume(): void + { + clearstatcache(); + if (is_file(static::$lockFile)) { + unlink(static::$lockFile); + } + } + + /** + * Whether monitor is paused + * @return bool + */ + public static function isPaused(): bool + { + clearstatcache(); + return file_exists(static::$lockFile); + } + + /** + * FileMonitor constructor. + * @param $monitorDir + * @param $monitorExtensions + * @param array $options + */ + public function __construct($monitorDir, $monitorExtensions, array $options = []) + { + static::resume(); + $this->paths = (array)$monitorDir; + $this->extensions = $monitorExtensions; + if (!Worker::getAllWorkers()) { + return; + } + $disableFunctions = explode(',', ini_get('disable_functions')); + if (in_array('exec', $disableFunctions, true)) { + echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n"; + } else { + if ($options['enable_file_monitor'] ?? true) { + Timer::add(1, function () { + $this->checkAllFilesChange(); + }); + } + } + + $memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null); + if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) { + Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]); + } + } + + /** + * @param $monitorDir + * @return bool + */ + public function checkFilesChange($monitorDir): bool + { + static $lastMtime, $tooManyFilesCheck; + if (!$lastMtime) { + $lastMtime = time(); + } + clearstatcache(); + if (!is_dir($monitorDir)) { + if (!is_file($monitorDir)) { + return false; + } + $iterator = [new SplFileInfo($monitorDir)]; + } else { + // recursive traversal directory + $dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS); + $iterator = new RecursiveIteratorIterator($dirIterator); + } + $count = 0; + foreach ($iterator as $file) { + $count ++; + /** var SplFileInfo $file */ + if (is_dir($file->getRealPath())) { + continue; + } + // check mtime + if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) { + $var = 0; + exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var); + $lastMtime = $file->getMTime(); + if ($var) { + continue; + } + echo $file . " update and reload\n"; + // send SIGUSR1 signal to master process for reload + if (DIRECTORY_SEPARATOR === '/') { + posix_kill(posix_getppid(), SIGUSR1); + } else { + return true; + } + break; + } + } + if (!$tooManyFilesCheck && $count > 1000) { + echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n"; + $tooManyFilesCheck = 1; + } + return false; + } + + /** + * @return bool + */ + public function checkAllFilesChange(): bool + { + if (static::isPaused()) { + return false; + } + foreach ($this->paths as $path) { + if ($this->checkFilesChange($path)) { + return true; + } + } + return false; + } + + /** + * @param $memoryLimit + * @return void + */ + public function checkMemory($memoryLimit) + { + if (static::isPaused() || $memoryLimit <= 0) { + return; + } + $ppid = posix_getppid(); + $childrenFile = "/proc/$ppid/task/$ppid/children"; + if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) { + return; + } + foreach (explode(' ', $children) as $pid) { + $pid = (int)$pid; + $statusFile = "/proc/$pid/status"; + if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) { + continue; + } + $mem = 0; + if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) { + $mem = $match[1]; + } + $mem = (int)($mem / 1024); + if ($mem >= $memoryLimit) { + posix_kill($pid, SIGINT); + } + } + } + + /** + * Get memory limit + * @return float + */ + protected function getMemoryLimit($memoryLimit) + { + if ($memoryLimit === 0) { + return 0; + } + $usePhpIni = false; + if (!$memoryLimit) { + $memoryLimit = ini_get('memory_limit'); + $usePhpIni = true; + } + + if ($memoryLimit == -1) { + return 0; + } + $unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]); + if ($unit === 'g') { + $memoryLimit = 1024 * (int)$memoryLimit; + } else if ($unit === 'm') { + $memoryLimit = (int)$memoryLimit; + } else if ($unit === 'k') { + $memoryLimit = ((int)$memoryLimit / 1024); + } else { + $memoryLimit = ((int)$memoryLimit / (1024 * 1024)); + } + if ($memoryLimit < 30) { + $memoryLimit = 30; + } + if ($usePhpIni) { + $memoryLimit = (int)(0.8 * $memoryLimit); + } + return $memoryLimit; + } +} diff --git a/cacme/public/404.html b/cacme/public/404.html new file mode 100644 index 0000000..2bde119 --- /dev/null +++ b/cacme/public/404.html @@ -0,0 +1,12 @@ + + + 404 Not Found - webman + + +
+

404 Not Found

+
+
+
webman
+ + diff --git a/cacme/public/favicon.ico b/cacme/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b9f722e0eeed8dc7f3639bd3295a7b0376b98eca GIT binary patch literal 4286 zcmbuDc}!GC9LI-{lvLYdn`%sIykgTPHU44S)cR&9&1g0})ukRu+b zsI4iH+Tum=wxm?+g|1x7X%O&eYs0dFEXuJv?|~SRU%$V%yN_jIWzi)cX5Q?Z`F`g& z^PBfT2tWLcA20Z~I66XzQ9_8f0h+{zfZMeXzI$!B14qNqe+Ms>0t^d|k|#hpcn^q~ z;CVg3dWG2j%ifLf3af($0x zFqHZ@&|>{}K^tIw<{IEO5%LUi;PHV0JOSi}L_G^kF%-24L#d6mnNZLTT>4y=fJs32 z>T3n#v;Jb>u1$s#{kl4$sCDYsB{mVVOo|!b%Y>Or`)Ip-WMT~hhU&qo|1rvkx`)Dc z3eN*q@6-It4HR~%KIfv@I@xr$`J)wSwu_-_>;xY!T~{fgJ^dN=dHt(3eaw6QQ5(&Q zwbSe!_bDQ$p3rC#TC=DQ1t2=B$w95sS3oCG8?O+V{O^KwP2A z#JKe59cj_##AAmi*eL7j1FC3lq3dmSsf7^;4_WBvlMm=;#>pmNa_ zbN6mz6D^FlYx?YA-dafqFMD`^pBqx8l17ELWJ#L6Tv|SjloLN+GW0x%FxdnZY!{J* zO>bu3zE@n@Xrm(g1kiF6>)}|NZnR~9*Ma-cgVuwiY@)K+DvIix zgRsv#uD3~jt+NXh3XhXo&T-yFZlPoKYP(QS z*TQ4y`W)ZW)fHq&oMLL^ISVq=dQNX$&xlL$K1x# z*7(XDl{RE3ywB*nWQl#}H3ly4Cosk+Zyun@=e8?%w36eyYL}hLt={+9v0{aOIj?AY z&fVhxb&f+O2n7A&0BwGLmwI}bwM^2!bF$w)ca6_E*FOh3kc$sBYV94a`E&Ugq}JFv zUI2YO@bePdQ$U|M@LuPAo?E48`R&s6T0+lcHq#kXA^lZmqVmQj`0L|ALEl9{RJ+9? zBwEvF5AT3{ps$4w`&^&nANhHd5c>@!tuxTZHQ}@=WhEJJ-SqVEFZ8Fd2lo#&S)Z8* z_5ps5X+Ag(Ntt}s_vQln>$*J0l6s4#{qxQkI&ok-*hafkmQvcTMCbFO_kQ%<4_@^2 zzeWJ+2eNu`#%p8DK354;Lol7p6fud@%wulH<1{44HRY0Ks{v&TtXTdEpTWA|O34LUvWxqcXMUTb6W9?1XuHtqZ&nG)l^rKAmuHEs4) zB@AIt%@K#v30S=-d0QdDYxZT9iy zD*2z!VqR{nZf6e)`*;iRdk3Gh&V8v;dak0+*M06>|6-+l@VPb}Ttsel z@|n4OhceLL37RLIYdu32dP)cEJ5k+^SlHD-nud)91PZ{o+ zzq%#)Txl0+$CLm(L*M6p4y`kYcOBka9)liSH{d#+x;9dMR}dLv$B}VbAQ?vokWn}= z3x8s4pi9FKr63Hx5d?v8ATSXag$OVU;co-o_?H7Z`k|xHI-r3NX+lrJ=!7o`Ul1Dq E2mbpSrT_o{ literal 0 HcmV?d00001 diff --git a/cacme/public/jquery-3.7.1.js b/cacme/public/jquery-3.7.1.js new file mode 100644 index 0000000..5a1e8cd --- /dev/null +++ b/cacme/public/jquery-3.7.1.js @@ -0,0 +1,10716 @@ +/*! + * jQuery JavaScript Library v3.7.1 + * https://jquery.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2023-08-28T13:37Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket trac-14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var version = "3.7.1", + + rhtmlSuffix = /HTML$/i, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + + // Retrieve the text value of an array of DOM nodes + text: function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += jQuery.text( node ); + } + } + if ( nodeType === 1 || nodeType === 11 ) { + return elem.textContent; + } + if ( nodeType === 9 ) { + return elem.documentElement.textContent; + } + if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + isXMLDoc: function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Assume HTML when documentElement doesn't yet exist, such as inside + // document fragments. + return !rhtmlSuffix.test( namespace || docElem && docElem.nodeName || "HTML" ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var pop = arr.pop; + + +var sort = arr.sort; + + +var splice = arr.splice; + + +var whitespace = "[\\x20\\t\\r\\n\\f]"; + + +var rtrimCSS = new RegExp( + "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", + "g" +); + + + + +// Note: an element does not contain itself +jQuery.contains = function( a, b ) { + var bup = b && b.parentNode; + + return a === bup || !!( bup && bup.nodeType === 1 && ( + + // Support: IE 9 - 11+ + // IE doesn't have `contains` on SVG. + a.contains ? + a.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); +}; + + + + +// CSS string/identifier serialization +// https://drafts.csswg.org/cssom/#common-serializing-idioms +var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; + +function fcssescape( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; +} + +jQuery.escapeSelector = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + + + + +var preferredDoc = document, + pushNative = push; + +( function() { + +var i, + Expr, + outermostContext, + sortInput, + hasDuplicate, + push = pushNative, + + // Local document vars + document, + documentElement, + documentIsHTML, + rbuggyQSA, + matches, + + // Instance-specific data + expando = jQuery.expando, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" + + "loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + + whitespace + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + ID: new RegExp( "^#(" + identifier + ")" ), + CLASS: new RegExp( "^\\.(" + identifier + ")" ), + TAG: new RegExp( "^(" + identifier + "|[*])" ), + ATTR: new RegExp( "^" + attributes ), + PSEUDO: new RegExp( "^" + pseudos ), + CHILD: new RegExp( + "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + bool: new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + needsContext: new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // https://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + if ( nonHex ) { + + // Strip the backslash prefix from a non-hex escape sequence + return nonHex; + } + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + return high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes; see `setDocument`. + // Support: IE 9 - 11+, Edge 12 - 18+ + // Removing the function wrapper causes a "Permission Denied" + // error in IE/Edge. + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && nodeName( elem, "fieldset" ); + }, + { dir: "parentNode", next: "legend" } + ); + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android <=4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { + apply: function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + }, + call: function( target ) { + pushNative.apply( target, slice.call( arguments, 1 ) ); + } + }; +} + +function find( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE 9 only + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + push.call( results, elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE 9 only + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + find.contains( context, elem ) && + elem.id === m ) { + + push.call( results, elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when + // strict-comparing two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( newContext != context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = jQuery.escapeSelector( nid ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrimCSS, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties + // (see https://github.com/jquery/sizzle/issues/157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by jQuery selector module + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + return nodeName( elem, "input" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) && + elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11+ + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a jQuery selector context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [node] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +function setDocument( node ) { + var subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + documentElement = document.documentElement; + documentIsHTML = !jQuery.isXMLDoc( document ); + + // Support: iOS 7 only, IE 9 - 11+ + // Older browsers didn't support unprefixed `matches`. + matches = documentElement.matches || + documentElement.webkitMatchesSelector || + documentElement.msMatchesSelector; + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors + // (see trac-13936). + // Limit the fix to IE & Edge Legacy; despite Edge 15+ implementing `matches`, + // all IE 9+ and Edge Legacy versions implement `msMatchesSelector` as well. + if ( documentElement.msMatchesSelector && + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 9 - 11+, Edge 12 - 18+ + subWindow.addEventListener( "unload", unloadHandler ); + } + + // Support: IE <10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + documentElement.appendChild( el ).id = jQuery.expando; + return !document.getElementsByName || + !document.getElementsByName( jQuery.expando ).length; + } ); + + // Support: IE 9 only + // Check to see if it's possible to do matchesSelector + // on a disconnected node. + support.disconnectedMatch = assert( function( el ) { + return matches.call( el, "*" ); + } ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // IE/Edge don't support the :scope pseudo-class. + support.scope = assert( function() { + return document.querySelectorAll( ":scope" ); + } ); + + // Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only + // Make sure the `:has()` argument is parsed unforgivingly. + // We include `*` in the test to detect buggy implementations that are + // _selectively_ forgiving (specifically when the list includes at least + // one valid selector). + // Note that we treat complete lack of support for `:has()` as if it were + // spec-compliant support, which is fine because use of `:has()` in such + // environments will fail in the qSA path and fall back to jQuery traversal + // anyway. + support.cssHas = assert( function() { + try { + document.querySelector( ":has(*,:jqfake)" ); + return false; + } catch ( e ) { + return true; + } + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter.ID = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find.ID = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter.ID = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find.ID = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find.TAG = function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else { + return context.querySelectorAll( tag ); + } + }; + + // Class + Expr.find.CLASS = function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + rbuggyQSA = []; + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + documentElement.appendChild( el ).innerHTML = + "" + + ""; + + // Support: iOS <=7 - 8 only + // Boolean attributes and "value" are not treated correctly in some XML documents + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: iOS <=7 - 8 only + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: iOS 8 only + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+ + // In some of the document kinds, these selectors wouldn't work natively. + // This is probably OK but for backwards compatibility we want to maintain + // handling them through jQuery traversal in jQuery 3.x. + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE 9 - 11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + // Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+ + // In some of the document kinds, these selectors wouldn't work natively. + // This is probably OK but for backwards compatibility we want to maintain + // handling them through jQuery traversal in jQuery 3.x. + documentElement.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + } ); + + if ( !support.cssHas ) { + + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Our regular `try-catch` mechanism fails to detect natively-unsupported + // pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`) + // in browsers that parse the `:has()` argument as a forgiving selector list. + // https://drafts.csswg.org/selectors/#relational now requires the argument + // to be parsed unforgivingly, but browsers have not yet fully adjusted. + rbuggyQSA.push( ":has" ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a === document || a.ownerDocument == preferredDoc && + find.contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b === document || b.ownerDocument == preferredDoc && + find.contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + }; + + return document; +} + +find.matches = function( expr, elements ) { + return find( expr, null, null, elements ); +}; + +find.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return find( expr, document, null, [ elem ] ).length > 0; +}; + +find.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return jQuery.contains( context, elem ); +}; + + +find.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (see trac-13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + if ( val !== undefined ) { + return val; + } + + return elem.getAttribute( name ); +}; + +find.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +jQuery.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + // + // Support: Android <=4.0+ + // Testing for detecting duplicates is unpredictable so instead assume we can't + // depend on duplicate detection in all browsers without a stable sort. + hasDuplicate = !support.sortStable; + sortInput = !support.sortStable && slice.call( results, 0 ); + sort.call( results, sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + splice.call( results, duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +jQuery.fn.uniqueSort = function() { + return this.pushStack( jQuery.uniqueSort( slice.apply( this ) ) ); +}; + +Expr = jQuery.expr = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + ATTR: function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" ) + .replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + CHILD: function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + find.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) + ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + find.error( match[ 0 ] ); + } + + return match; + }, + + PSEUDO: function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr.CHILD.test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + TAG: function( nodeNameSelector ) { + var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return nodeName( elem, expectedNodeName ); + }; + }, + + CLASS: function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + ")" + className + + "(" + whitespace + "|$)" ) ) && + classCache( className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + ATTR: function( name, operator, check ) { + return function( elem ) { + var result = find.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + if ( operator === "=" ) { + return result === check; + } + if ( operator === "!=" ) { + return result !== check; + } + if ( operator === "^=" ) { + return check && result.indexOf( check ) === 0; + } + if ( operator === "*=" ) { + return check && result.indexOf( check ) > -1; + } + if ( operator === "$=" ) { + return check && result.slice( -check.length ) === check; + } + if ( operator === "~=" ) { + return ( " " + result.replace( rwhitespace, " " ) + " " ) + .indexOf( check ) > -1; + } + if ( operator === "|=" ) { + return result === check || result.slice( 0, check.length + 1 ) === check + "-"; + } + + return false; + }; + }, + + CHILD: function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + nodeName( node, name ) : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || ( parent[ expando ] = {} ); + cache = outerCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + cache = outerCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + nodeName( node, name ) : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + outerCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + PSEUDO: function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // https://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + find.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as jQuery does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + not: markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrimCSS, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element + // (see https://github.com/jquery/sizzle/issues/299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + has: markFunction( function( selector ) { + return function( elem ) { + return find( selector, elem ).length > 0; + }; + } ), + + contains: markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // https://www.w3.org/TR/selectors/#lang-pseudo + lang: markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + find.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + target: function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + root: function( elem ) { + return elem === documentElement; + }, + + focus: function( elem ) { + return elem === safeActiveElement() && + document.hasFocus() && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + enabled: createDisabledPseudo( false ), + disabled: createDisabledPseudo( true ), + + checked: function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + return ( nodeName( elem, "input" ) && !!elem.checked ) || + ( nodeName( elem, "option" ) && !!elem.selected ); + }, + + selected: function( elem ) { + + // Support: IE <=11+ + // Accessing the selectedIndex property + // forces the browser to treat the default option as + // selected when in an optgroup. + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + empty: function( elem ) { + + // https://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + parent: function( elem ) { + return !Expr.pseudos.empty( elem ); + }, + + // Element/input types + header: function( elem ) { + return rheader.test( elem.nodeName ); + }, + + input: function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + button: function( elem ) { + return nodeName( elem, "input" ) && elem.type === "button" || + nodeName( elem, "button" ); + }, + + text: function( elem ) { + var attr; + return nodeName( elem, "input" ) && elem.type === "text" && + + // Support: IE <10 only + // New HTML5 attribute values (e.g., "search") appear + // with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + first: createPositionalPseudo( function() { + return [ 0 ]; + } ), + + last: createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + eq: createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + even: createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + odd: createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + lt: createPositionalPseudo( function( matchIndexes, length, argument ) { + var i; + + if ( argument < 0 ) { + i = argument + length; + } else if ( argument > length ) { + i = length; + } else { + i = argument; + } + + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + gt: createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos.nth = Expr.pseudos.eq; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rleadingCombinator.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrimCSS, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + if ( parseOnly ) { + return soFar.length; + } + + return soFar ? + find.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + if ( skip && nodeName( elem, skip ) ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = outerCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + outerCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + find( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, matcherOut, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || + multipleContexts( selector || "*", + context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems; + + if ( matcher ) { + + // If we have a postFinder, or filtered seed, or non-seed postFilter + // or preexisting results, + matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results; + + // Find primary matches + matcher( matcherIn, matcherOut, context, xml ); + } else { + matcherOut = matcherIn; + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element + // (see https://github.com/jquery/sizzle/issues/299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrimCSS, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find.TAG( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: iOS <=7 - 9 only + // Tolerate NodeList properties (IE: "length"; Safari: ) matching + // elements by id. (see trac-14142) + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + push.call( results, elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + jQuery.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +function compile( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +} + +/** + * A low-level selection function that works with jQuery's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with jQuery selector compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find.ID( + token.matches[ 0 ].replace( runescape, funescape ), + context + ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && + testContext( context.parentNode ) || context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +} + +// One-time assignments + +// Support: Android <=4.0 - 4.1+ +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Initialize against the default document +setDocument(); + +// Support: Android <=4.0 - 4.1+ +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +jQuery.find = find; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.unique = jQuery.uniqueSort; + +// These have always been private, but they used to be documented as part of +// Sizzle so let's maintain them for now for backwards compatibility purposes. +find.compile = compile; +find.select = select; +find.setDocument = setDocument; +find.tokenize = tokenize; + +find.escape = jQuery.escapeSelector; +find.getText = jQuery.text; +find.isXML = jQuery.isXMLDoc; +find.selectors = jQuery.expr; +find.support = jQuery.support; +find.uniqueSort = jQuery.uniqueSort; + + /* eslint-enable */ + +} )(); + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (trac-9521) + // Strict HTML recognition (trac-11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to jQuery#find + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.error ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the error, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getErrorHook ) { + process.error = jQuery.Deferred.getErrorHook(); + + // The deprecated alias of the above. While the name suggests + // returning the stack, not an error instance, jQuery just passes + // it directly to `console.warn` so both will work; an instance + // just better cooperates with source maps. + } else if ( jQuery.Deferred.getStackHook ) { + process.error = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +// If `jQuery.Deferred.getErrorHook` is defined, `asyncError` is an error +// captured before the async barrier to get the original error cause +// which may otherwise be hidden. +jQuery.Deferred.exceptionHook = function( error, asyncError ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, + error.stack, asyncError ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See trac-6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (trac-9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see trac-8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (trac-14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (trac-11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (trac-14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (trac-13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (trac-15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (trac-12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (trac-13208) + // Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (trac-13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", true ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, isSetup ) { + + // Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add + if ( !isSetup ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + if ( !saved ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + this[ type ](); + result = dataPriv.get( this, type ); + dataPriv.set( this, type, false ); + + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + return result; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering + // the native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved ) { + + // ...and capture the result + dataPriv.set( this, type, jQuery.event.trigger( + saved[ 0 ], + saved.slice( 1 ), + this + ) ); + + // Abort handling of the native event by all jQuery handlers while allowing + // native handlers on the same element to run. On target, this is achieved + // by stopping immediate propagation just on the jQuery event. However, + // the native event is re-wrapped by a jQuery one on each level of the + // propagation so the only way to stop it for jQuery is to stop it for + // everyone via native `stopPropagation()`. This is not a problem for + // focus/blur which don't bubble, but it does also stop click on checkboxes + // and radios. We accept this limitation. + event.stopPropagation(); + event.isImmediatePropagationStopped = returnTrue; + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (trac-504, trac-13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + + function focusMappedHandler( nativeEvent ) { + if ( document.documentMode ) { + + // Support: IE 11+ + // Attach a single focusin/focusout handler on the document while someone wants + // focus/blur. This is because the former are synchronous in IE while the latter + // are async. In other browsers, all those handlers are invoked synchronously. + + // `handle` from private data would already wrap the event, but we need + // to change the `type` here. + var handle = dataPriv.get( this, "handle" ), + event = jQuery.event.fix( nativeEvent ); + event.type = nativeEvent.type === "focusin" ? "focus" : "blur"; + event.isSimulated = true; + + // First, handle focusin/focusout + handle( nativeEvent ); + + // ...then, handle focus/blur + // + // focus/blur don't bubble while focusin/focusout do; simulate the former by only + // invoking the handler at the lower level. + if ( event.target === event.currentTarget ) { + + // The setup part calls `leverageNative`, which, in turn, calls + // `jQuery.event.add`, so event handle will already have been set + // by this point. + handle( event ); + } + } else { + + // For non-IE browsers, attach a single capturing handler on the document + // while someone wants focusin/focusout. + jQuery.event.simulate( delegateType, nativeEvent.target, + jQuery.event.fix( nativeEvent ) ); + } + } + + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + var attaches; + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, true ); + + if ( document.documentMode ) { + + // Support: IE 9 - 11+ + // We use the same native handler for focusin & focus (and focusout & blur) + // so we need to coordinate setup & teardown parts between those events. + // Use `delegateType` as the key as `type` is already used by `leverageNative`. + attaches = dataPriv.get( this, delegateType ); + if ( !attaches ) { + this.addEventListener( delegateType, focusMappedHandler ); + } + dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 ); + } else { + + // Return false to allow normal processing in the caller + return false; + } + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + teardown: function() { + var attaches; + + if ( document.documentMode ) { + attaches = dataPriv.get( this, delegateType ) - 1; + if ( !attaches ) { + this.removeEventListener( delegateType, focusMappedHandler ); + dataPriv.remove( this, delegateType ); + } else { + dataPriv.set( this, delegateType, attaches ); + } + } else { + + // Return false to indicate standard teardown should be applied + return false; + } + }, + + // Suppress native focus or blur if we're currently inside + // a leveraged native-event stack + _default: function( event ) { + return dataPriv.get( event.target, type ); + }, + + delegateType: delegateType + }; + + // Support: Firefox <=44 + // Firefox doesn't have focus(in | out) events + // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 + // + // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 + // focus(in | out) events fire after focus & blur events, + // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order + // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 + // + // Support: IE 9 - 11+ + // To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch, + // attach a single handler for both events in IE. + jQuery.event.special[ delegateType ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + dataHolder = document.documentMode ? this : doc, + attaches = dataPriv.get( dataHolder, delegateType ); + + // Support: IE 9 - 11+ + // We use the same native handler for focusin & focus (and focusout & blur) + // so we need to coordinate setup & teardown parts between those events. + // Use `delegateType` as the key as `type` is already used by `leverageNative`. + if ( !attaches ) { + if ( document.documentMode ) { + this.addEventListener( delegateType, focusMappedHandler ); + } else { + doc.addEventListener( type, focusMappedHandler, true ); + } + } + dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + dataHolder = document.documentMode ? this : doc, + attaches = dataPriv.get( dataHolder, delegateType ) - 1; + + if ( !attaches ) { + if ( document.documentMode ) { + this.removeEventListener( delegateType, focusMappedHandler ); + } else { + doc.removeEventListener( type, focusMappedHandler, true ); + } + dataPriv.remove( dataHolder, delegateType ); + } else { + dataPriv.set( dataHolder, delegateType, attaches ); + } + } + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (trac-8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Re-enable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + + // Unwrap a CDATA section containing script contents. This shouldn't be + // needed as in XML documents they're already not visible when + // inspecting element contents and in HTML documents they have no + // meaning but we're preserving that logic for backwards compatibility. + // This will be removed completely in 4.0. See gh-4904. + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew jQuery#find here for performance reasons: + // https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var rcustomProp = /^--/; + + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (trac-15098, trac-14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (trac-8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "box-sizing:content-box;border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is `display: block` + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + isCustomProp = rcustomProp.test( name ), + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, trac-12537) + // .css('--customProperty) (gh-3144) + if ( computed ) { + + // Support: IE <=9 - 11+ + // IE only supports `"float"` in `getPropertyValue`; in computed styles + // it's only available as `"cssFloat"`. We no longer modify properties + // sent to `.css()` apart from camelCasing, so we need to check both. + // Normally, this would create difference in behavior: if + // `getPropertyValue` returns an empty string, the value returned + // by `.css()` would be `undefined`. This is usually the case for + // disconnected elements. However, in IE even disconnected elements + // with no styles return `"none"` for `getPropertyValue( "float" )` + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( isCustomProp && ret ) { + + // Support: Firefox 105+, Chrome <=105+ + // Spec requires trimming whitespace for custom properties (gh-4926). + // Firefox only trims leading whitespace. Chrome just collapses + // both leading & trailing whitespace to a single space. + // + // Fall back to `undefined` if empty string returned. + // This collapses a missing definition with property defined + // and set to an empty string but there's no standard API + // allowing us to differentiate them without a performance penalty + // and returning `undefined` aligns with older jQuery. + // + // rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED + // as whitespace while CSS does not, but this is not a problem + // because CSS preprocessing replaces them with U+000A LINE FEED + // (which *is* CSS whitespace) + // https://www.w3.org/TR/css-syntax-3/#input-preprocessing + ret = ret.replace( rtrimCSS, "$1" ) || undefined; + } + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0, + marginDelta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + // Count margin delta separately to only add it after scroll gutter adjustment. + // This is needed to make negative margins work with `outerHeight( true )` (gh-3982). + if ( box === "margin" ) { + marginDelta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta + marginDelta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + animationIterationCount: true, + aspectRatio: true, + borderImageSlice: true, + columnCount: true, + flexGrow: true, + flexShrink: true, + fontWeight: true, + gridArea: true, + gridColumn: true, + gridColumnEnd: true, + gridColumnStart: true, + gridRow: true, + gridRowEnd: true, + gridRowStart: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + scale: true, + widows: true, + zIndex: true, + zoom: true, + + // SVG-related + fillOpacity: true, + floodOpacity: true, + stopOpacity: true, + strokeMiterlimit: true, + strokeOpacity: true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (trac-7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug trac-9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (trac-7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // Use proper attribute retrieval (trac-12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classNames, cur, curValue, className, i, finalValue; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classNames = classesToArray( value ); + + if ( classNames.length ) { + return this.each( function() { + curValue = getClass( this ); + cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; + if ( cur.indexOf( " " + className + " " ) < 0 ) { + cur += className + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + this.setAttribute( "class", finalValue ); + } + } + } ); + } + + return this; + }, + + removeClass: function( value ) { + var classNames, cur, curValue, className, i, finalValue; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classNames = classesToArray( value ); + + if ( classNames.length ) { + return this.each( function() { + curValue = getClass( this ); + + // This expression is here for better compressibility (see addClass) + cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; + + // Remove *all* instances + while ( cur.indexOf( " " + className + " " ) > -1 ) { + cur = cur.replace( " " + className + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + this.setAttribute( "class", finalValue ); + } + } + } ); + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var classNames, className, i, self, + type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + classNames = classesToArray( value ); + + return this.each( function() { + if ( isValidValue ) { + + // Toggle individual class names + self = jQuery( this ); + + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (trac-14686, trac-14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (trac-2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (trac-9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (trac-9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (trac-6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // trac-7653, trac-8125, trac-8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes trac-9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (trac-10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket trac-12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (trac-15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // trac-9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (trac-11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // trac-1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see trac-8605, trac-14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // trac-14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "'); + } elseif ($format === self::FORMAT_JS) { + static::writeOutput(static::generateScript()); + } + static::resetStatic(); + } + } + + public function close(): void + { + self::resetStatic(); + } + + public function reset() + { + parent::reset(); + + self::resetStatic(); + } + + /** + * Forget all logged records + */ + public static function resetStatic(): void + { + static::$records = []; + } + + /** + * Wrapper for register_shutdown_function to allow overriding + */ + protected function registerShutdownFunction(): void + { + if (PHP_SAPI !== 'cli') { + register_shutdown_function(['Monolog\Handler\BrowserConsoleHandler', 'send']); + } + } + + /** + * Wrapper for echo to allow overriding + */ + protected static function writeOutput(string $str): void + { + echo $str; + } + + /** + * Checks the format of the response + * + * If Content-Type is set to application/javascript or text/javascript -> js + * If Content-Type is set to text/html, or is unset -> html + * If Content-Type is anything else -> unknown + * + * @return string One of 'js', 'html' or 'unknown' + * @phpstan-return self::FORMAT_* + */ + protected static function getResponseFormat(): string + { + // Check content type + foreach (headers_list() as $header) { + if (stripos($header, 'content-type:') === 0) { + return static::getResponseFormatFromContentType($header); + } + } + + return self::FORMAT_HTML; + } + + /** + * @return string One of 'js', 'html' or 'unknown' + * @phpstan-return self::FORMAT_* + */ + protected static function getResponseFormatFromContentType(string $contentType): string + { + // This handler only works with HTML and javascript outputs + // text/javascript is obsolete in favour of application/javascript, but still used + if (stripos($contentType, 'application/javascript') !== false || stripos($contentType, 'text/javascript') !== false) { + return self::FORMAT_JS; + } + + if (stripos($contentType, 'text/html') !== false) { + return self::FORMAT_HTML; + } + + return self::FORMAT_UNKNOWN; + } + + private static function generateScript(): string + { + $script = []; + foreach (static::$records as $record) { + $context = static::dump('Context', $record['context']); + $extra = static::dump('Extra', $record['extra']); + + if (empty($context) && empty($extra)) { + $script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted'])); + } else { + $script = array_merge( + $script, + [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))], + $context, + $extra, + [static::call('groupEnd')] + ); + } + } + + return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; + } + + private static function getConsoleMethodForLevel(int $level): string + { + return [ + Logger::DEBUG => 'debug', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warn', + Logger::ERROR => 'error', + Logger::CRITICAL => 'error', + Logger::ALERT => 'error', + Logger::EMERGENCY => 'error', + ][$level] ?? 'log'; + } + + /** + * @return string[] + */ + private static function handleStyles(string $formatted): array + { + $args = []; + $format = '%c' . $formatted; + preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + + foreach (array_reverse($matches) as $match) { + $args[] = '"font-weight: normal"'; + $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0])); + + $pos = $match[0][1]; + $format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0])); + } + + $args[] = static::quote('font-weight: normal'); + $args[] = static::quote($format); + + return array_reverse($args); + } + + private static function handleCustomStyles(string $style, string $string): string + { + static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey']; + static $labels = []; + + $style = preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function (array $m) use ($string, &$colors, &$labels) { + if (trim($m[1]) === 'autolabel') { + // Format the string as a label with consistent auto assigned background color + if (!isset($labels[$string])) { + $labels[$string] = $colors[count($labels) % count($colors)]; + } + $color = $labels[$string]; + + return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px"; + } + + return $m[1]; + }, $style); + + if (null === $style) { + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); + } + + return $style; + } + + /** + * @param mixed[] $dict + * @return mixed[] + */ + private static function dump(string $title, array $dict): array + { + $script = []; + $dict = array_filter($dict); + if (empty($dict)) { + return $script; + } + $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title)); + foreach ($dict as $key => $value) { + $value = json_encode($value); + if (empty($value)) { + $value = static::quote(''); + } + $script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value); + } + + return $script; + } + + private static function quote(string $arg): string + { + return '"' . addcslashes($arg, "\"\n\\") . '"'; + } + + /** + * @param mixed $args + */ + private static function call(...$args): string + { + $method = array_shift($args); + if (!is_string($method)) { + throw new \UnexpectedValueException('Expected the first arg to be a string, got: '.var_export($method, true)); + } + + return static::call_array($method, $args); + } + + /** + * @param mixed[] $args + */ + private static function call_array(string $method, array $args): string + { + return 'c.' . $method . '(' . implode(', ', $args) . ');'; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php new file mode 100644 index 0000000..fcce5d6 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php @@ -0,0 +1,167 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\ResettableInterface; +use Monolog\Formatter\FormatterInterface; + +/** + * Buffers all records until closing the handler and then pass them as batch. + * + * This is useful for a MailHandler to send only one mail per request instead of + * sending one per log message. + * + * @author Christophe Coevoet + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface +{ + use ProcessableHandlerTrait; + + /** @var HandlerInterface */ + protected $handler; + /** @var int */ + protected $bufferSize = 0; + /** @var int */ + protected $bufferLimit; + /** @var bool */ + protected $flushOnOverflow; + /** @var Record[] */ + protected $buffer = []; + /** @var bool */ + protected $initialized = false; + + /** + * @param HandlerInterface $handler Handler. + * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded + */ + public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false) + { + parent::__construct($level, $bubble); + $this->handler = $handler; + $this->bufferLimit = $bufferLimit; + $this->flushOnOverflow = $flushOnOverflow; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if ($record['level'] < $this->level) { + return false; + } + + if (!$this->initialized) { + // __destructor() doesn't get called on Fatal errors + register_shutdown_function([$this, 'close']); + $this->initialized = true; + } + + if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) { + if ($this->flushOnOverflow) { + $this->flush(); + } else { + array_shift($this->buffer); + $this->bufferSize--; + } + } + + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + $this->buffer[] = $record; + $this->bufferSize++; + + return false === $this->bubble; + } + + public function flush(): void + { + if ($this->bufferSize === 0) { + return; + } + + $this->handler->handleBatch($this->buffer); + $this->clear(); + } + + public function __destruct() + { + // suppress the parent behavior since we already have register_shutdown_function() + // to call close(), and the reference contained there will prevent this from being + // GC'd until the end of the request + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + $this->flush(); + + $this->handler->close(); + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + */ + public function clear(): void + { + $this->bufferSize = 0; + $this->buffer = []; + } + + public function reset() + { + $this->flush(); + + parent::reset(); + + $this->resetProcessors(); + + if ($this->handler instanceof ResettableInterface) { + $this->handler->reset(); + } + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + if ($this->handler instanceof FormattableHandlerInterface) { + $this->handler->setFormatter($formatter); + + return $this; + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + if ($this->handler instanceof FormattableHandlerInterface) { + return $this->handler->getFormatter(); + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php new file mode 100644 index 0000000..234ecf6 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php @@ -0,0 +1,196 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\ChromePHPFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Monolog\Utils; + +/** + * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) + * + * This also works out of the box with Firefox 43+ + * + * @author Christophe Coevoet + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class ChromePHPHandler extends AbstractProcessingHandler +{ + use WebRequestRecognizerTrait; + + /** + * Version of the extension + */ + protected const VERSION = '4.0'; + + /** + * Header name + */ + protected const HEADER_NAME = 'X-ChromeLogger-Data'; + + /** + * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+) + */ + protected const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}'; + + /** @var bool */ + protected static $initialized = false; + + /** + * Tracks whether we sent too much data + * + * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending + * + * @var bool + */ + protected static $overflowed = false; + + /** @var mixed[] */ + protected static $json = [ + 'version' => self::VERSION, + 'columns' => ['label', 'log', 'backtrace', 'type'], + 'rows' => [], + ]; + + /** @var bool */ + protected static $sendHeaders = true; + + public function __construct($level = Logger::DEBUG, bool $bubble = true) + { + parent::__construct($level, $bubble); + if (!function_exists('json_encode')) { + throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler'); + } + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + if (!$this->isWebRequest()) { + return; + } + + $messages = []; + + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + /** @var Record $message */ + $message = $this->processRecord($record); + $messages[] = $message; + } + + if (!empty($messages)) { + $messages = $this->getFormatter()->formatBatch($messages); + self::$json['rows'] = array_merge(self::$json['rows'], $messages); + $this->send(); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new ChromePHPFormatter(); + } + + /** + * Creates & sends header for a record + * + * @see sendHeader() + * @see send() + */ + protected function write(array $record): void + { + if (!$this->isWebRequest()) { + return; + } + + self::$json['rows'][] = $record['formatted']; + + $this->send(); + } + + /** + * Sends the log header + * + * @see sendHeader() + */ + protected function send(): void + { + if (self::$overflowed || !self::$sendHeaders) { + return; + } + + if (!self::$initialized) { + self::$initialized = true; + + self::$sendHeaders = $this->headersAccepted(); + if (!self::$sendHeaders) { + return; + } + + self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? ''; + } + + $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); + $data = base64_encode($json); + if (strlen($data) > 3 * 1024) { + self::$overflowed = true; + + $record = [ + 'message' => 'Incomplete logs, chrome header size limit reached', + 'context' => [], + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'monolog', + 'datetime' => new \DateTimeImmutable(), + 'extra' => [], + ]; + self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); + $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); + $data = base64_encode($json); + } + + if (trim($data) !== '') { + $this->sendHeader(static::HEADER_NAME, $data); + } + } + + /** + * Send header string to the client + */ + protected function sendHeader(string $header, string $content): void + { + if (!headers_sent() && self::$sendHeaders) { + header(sprintf('%s: %s', $header, $content)); + } + } + + /** + * Verifies if the headers are accepted by the current user agent + */ + protected function headersAccepted(): bool + { + if (empty($_SERVER['HTTP_USER_AGENT'])) { + return false; + } + + return preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php new file mode 100644 index 0000000..5265761 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\JsonFormatter; +use Monolog\Logger; + +/** + * CouchDB handler + * + * @author Markus Bachmann + */ +class CouchDBHandler extends AbstractProcessingHandler +{ + /** @var mixed[] */ + private $options; + + /** + * @param mixed[] $options + */ + public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true) + { + $this->options = array_merge([ + 'host' => 'localhost', + 'port' => 5984, + 'dbname' => 'logger', + 'username' => null, + 'password' => null, + ], $options); + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $basicAuth = null; + if ($this->options['username']) { + $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); + } + + $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname']; + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'content' => $record['formatted'], + 'ignore_errors' => true, + 'max_redirects' => 0, + 'header' => 'Content-type: application/json', + ], + ]); + + if (false === @file_get_contents($url, false, $context)) { + throw new \RuntimeException(sprintf('Could not connect to %s', $url)); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php new file mode 100644 index 0000000..3535a4f --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -0,0 +1,167 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; + +/** + * Logs to Cube. + * + * @link https://github.com/square/cube/wiki + * @author Wan Chen + * @deprecated Since 2.8.0 and 3.2.0, Cube appears abandoned and thus we will drop this handler in Monolog 4 + */ +class CubeHandler extends AbstractProcessingHandler +{ + /** @var resource|\Socket|null */ + private $udpConnection = null; + /** @var resource|\CurlHandle|null */ + private $httpConnection = null; + /** @var string */ + private $scheme; + /** @var string */ + private $host; + /** @var int */ + private $port; + /** @var string[] */ + private $acceptedSchemes = ['http', 'udp']; + + /** + * Create a Cube handler + * + * @throws \UnexpectedValueException when given url is not a valid url. + * A valid url must consist of three parts : protocol://host:port + * Only valid protocols used by Cube are http and udp + */ + public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true) + { + $urlInfo = parse_url($url); + + if ($urlInfo === false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) { + throw new \UnexpectedValueException('URL "'.$url.'" is not valid'); + } + + if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) { + throw new \UnexpectedValueException( + 'Invalid protocol (' . $urlInfo['scheme'] . ').' + . ' Valid options are ' . implode(', ', $this->acceptedSchemes) + ); + } + + $this->scheme = $urlInfo['scheme']; + $this->host = $urlInfo['host']; + $this->port = (int) $urlInfo['port']; + + parent::__construct($level, $bubble); + } + + /** + * Establish a connection to an UDP socket + * + * @throws \LogicException when unable to connect to the socket + * @throws MissingExtensionException when there is no socket extension + */ + protected function connectUdp(): void + { + if (!extension_loaded('sockets')) { + throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler'); + } + + $udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0); + if (false === $udpConnection) { + throw new \LogicException('Unable to create a socket'); + } + + $this->udpConnection = $udpConnection; + if (!socket_connect($this->udpConnection, $this->host, $this->port)) { + throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port); + } + } + + /** + * Establish a connection to an http server + * + * @throws \LogicException when unable to connect to the socket + * @throws MissingExtensionException when no curl extension + */ + protected function connectHttp(): void + { + if (!extension_loaded('curl')) { + throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler'); + } + + $httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put'); + if (false === $httpConnection) { + throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port); + } + + $this->httpConnection = $httpConnection; + curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $date = $record['datetime']; + + $data = ['time' => $date->format('Y-m-d\TH:i:s.uO')]; + unset($record['datetime']); + + if (isset($record['context']['type'])) { + $data['type'] = $record['context']['type']; + unset($record['context']['type']); + } else { + $data['type'] = $record['channel']; + } + + $data['data'] = $record['context']; + $data['data']['level'] = $record['level']; + + if ($this->scheme === 'http') { + $this->writeHttp(Utils::jsonEncode($data)); + } else { + $this->writeUdp(Utils::jsonEncode($data)); + } + } + + private function writeUdp(string $data): void + { + if (!$this->udpConnection) { + $this->connectUdp(); + } + + socket_send($this->udpConnection, $data, strlen($data), 0); + } + + private function writeHttp(string $data): void + { + if (!$this->httpConnection) { + $this->connectHttp(); + } + + if (null === $this->httpConnection) { + throw new \LogicException('No connection could be established'); + } + + curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']'); + curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'Content-Length: ' . strlen('['.$data.']'), + ]); + + Curl\Util::execute($this->httpConnection, 5, false); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php new file mode 100644 index 0000000..7213e8e --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.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 Monolog\Handler\Curl; + +use CurlHandle; + +/** + * This class is marked as internal and it is not under the BC promise of the package. + * + * @internal + */ +final class Util +{ + /** @var array */ + private static $retriableErrorCodes = [ + CURLE_COULDNT_RESOLVE_HOST, + CURLE_COULDNT_CONNECT, + CURLE_HTTP_NOT_FOUND, + CURLE_READ_ERROR, + CURLE_OPERATION_TIMEOUTED, + CURLE_HTTP_POST_ERROR, + CURLE_SSL_CONNECT_ERROR, + ]; + + /** + * Executes a CURL request with optional retries and exception on failure + * + * @param resource|CurlHandle $ch curl handler + * @param int $retries + * @param bool $closeAfterDone + * @return bool|string @see curl_exec + */ + public static function execute($ch, int $retries = 5, bool $closeAfterDone = true) + { + while ($retries--) { + $curlResponse = curl_exec($ch); + if ($curlResponse === false) { + $curlErrno = curl_errno($ch); + + if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) { + $curlError = curl_error($ch); + + if ($closeAfterDone) { + curl_close($ch); + } + + throw new \RuntimeException(sprintf('Curl error (code %d): %s', $curlErrno, $curlError)); + } + + continue; + } + + if ($closeAfterDone) { + curl_close($ch); + } + + return $curlResponse; + } + + return false; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php new file mode 100644 index 0000000..9b85ae7 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php @@ -0,0 +1,186 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Simple handler wrapper that deduplicates log records across multiple requests + * + * It also includes the BufferHandler functionality and will buffer + * all messages until the end of the request or flush() is called. + * + * This works by storing all log records' messages above $deduplicationLevel + * to the file specified by $deduplicationStore. When further logs come in at the end of the + * request (or when flush() is called), all those above $deduplicationLevel are checked + * against the existing stored logs. If they match and the timestamps in the stored log is + * not older than $time seconds, the new log record is discarded. If no log record is new, the + * whole data set is discarded. + * + * This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers + * that send messages to people, to avoid spamming with the same message over and over in case of + * a major component failure like a database server being down which makes all requests fail in the + * same way. + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + */ +class DeduplicationHandler extends BufferHandler +{ + /** + * @var string + */ + protected $deduplicationStore; + + /** + * @var Level + */ + protected $deduplicationLevel; + + /** + * @var int + */ + protected $time; + + /** + * @var bool + */ + private $gc = false; + + /** + * @param HandlerInterface $handler Handler. + * @param string $deduplicationStore The file/path where the deduplication log should be kept + * @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes + * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * + * @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel + */ + public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true) + { + parent::__construct($handler, 0, Logger::DEBUG, $bubble, false); + + $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore; + $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel); + $this->time = $time; + } + + public function flush(): void + { + if ($this->bufferSize === 0) { + return; + } + + $passthru = null; + + foreach ($this->buffer as $record) { + if ($record['level'] >= $this->deduplicationLevel) { + $passthru = $passthru || !$this->isDuplicate($record); + if ($passthru) { + $this->appendRecord($record); + } + } + } + + // default of null is valid as well as if no record matches duplicationLevel we just pass through + if ($passthru === true || $passthru === null) { + $this->handler->handleBatch($this->buffer); + } + + $this->clear(); + + if ($this->gc) { + $this->collectLogs(); + } + } + + /** + * @phpstan-param Record $record + */ + private function isDuplicate(array $record): bool + { + if (!file_exists($this->deduplicationStore)) { + return false; + } + + $store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if (!is_array($store)) { + return false; + } + + $yesterday = time() - 86400; + $timestampValidity = $record['datetime']->getTimestamp() - $this->time; + $expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']); + + for ($i = count($store) - 1; $i >= 0; $i--) { + list($timestamp, $level, $message) = explode(':', $store[$i], 3); + + if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) { + return true; + } + + if ($timestamp < $yesterday) { + $this->gc = true; + } + } + + return false; + } + + private function collectLogs(): void + { + if (!file_exists($this->deduplicationStore)) { + return; + } + + $handle = fopen($this->deduplicationStore, 'rw+'); + + if (!$handle) { + throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore); + } + + flock($handle, LOCK_EX); + $validLogs = []; + + $timestampValidity = time() - $this->time; + + while (!feof($handle)) { + $log = fgets($handle); + if ($log && substr($log, 0, 10) >= $timestampValidity) { + $validLogs[] = $log; + } + } + + ftruncate($handle, 0); + rewind($handle); + foreach ($validLogs as $log) { + fwrite($handle, $log); + } + + flock($handle, LOCK_UN); + fclose($handle); + + $this->gc = false; + } + + /** + * @phpstan-param Record $record + */ + private function appendRecord(array $record): void + { + file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php new file mode 100644 index 0000000..ebd52c3 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; +use Monolog\Formatter\FormatterInterface; +use Doctrine\CouchDB\CouchDBClient; + +/** + * CouchDB handler for Doctrine CouchDB ODM + * + * @author Markus Bachmann + */ +class DoctrineCouchDBHandler extends AbstractProcessingHandler +{ + /** @var CouchDBClient */ + private $client; + + public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true) + { + $this->client = $client; + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->client->postDocument($record['formatted']); + } + + protected function getDefaultFormatter(): FormatterInterface + { + return new NormalizerFormatter; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php new file mode 100644 index 0000000..21840bf --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.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 Monolog\Handler; + +use Aws\Sdk; +use Aws\DynamoDb\DynamoDbClient; +use Monolog\Formatter\FormatterInterface; +use Aws\DynamoDb\Marshaler; +use Monolog\Formatter\ScalarFormatter; +use Monolog\Logger; + +/** + * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) + * + * @link https://github.com/aws/aws-sdk-php/ + * @author Andrew Lawson + */ +class DynamoDbHandler extends AbstractProcessingHandler +{ + public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; + + /** + * @var DynamoDbClient + */ + protected $client; + + /** + * @var string + */ + protected $table; + + /** + * @var int + */ + protected $version; + + /** + * @var Marshaler + */ + protected $marshaler; + + public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true) + { + /** @phpstan-ignore-next-line */ + if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) { + $this->version = 3; + $this->marshaler = new Marshaler; + } else { + $this->version = 2; + } + + $this->client = $client; + $this->table = $table; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $filtered = $this->filterEmptyFields($record['formatted']); + if ($this->version === 3) { + $formatted = $this->marshaler->marshalItem($filtered); + } else { + /** @phpstan-ignore-next-line */ + $formatted = $this->client->formatAttributes($filtered); + } + + $this->client->putItem([ + 'TableName' => $this->table, + 'Item' => $formatted, + ]); + } + + /** + * @param mixed[] $record + * @return mixed[] + */ + protected function filterEmptyFields(array $record): array + { + return array_filter($record, function ($value) { + return !empty($value) || false === $value || 0 === $value; + }); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new ScalarFormatter(self::DATE_FORMAT); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php new file mode 100644 index 0000000..fc92ca4 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Elastica\Document; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\ElasticaFormatter; +use Monolog\Logger; +use Elastica\Client; +use Elastica\Exception\ExceptionInterface; + +/** + * Elastic Search handler + * + * Usage example: + * + * $client = new \Elastica\Client(); + * $options = array( + * 'index' => 'elastic_index_name', + * 'type' => 'elastic_doc_type', Types have been removed in Elastica 7 + * ); + * $handler = new ElasticaHandler($client, $options); + * $log = new Logger('application'); + * $log->pushHandler($handler); + * + * @author Jelle Vink + */ +class ElasticaHandler extends AbstractProcessingHandler +{ + /** + * @var Client + */ + protected $client; + + /** + * @var mixed[] Handler config options + */ + protected $options = []; + + /** + * @param Client $client Elastica Client object + * @param mixed[] $options Handler configuration + */ + public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) + { + parent::__construct($level, $bubble); + $this->client = $client; + $this->options = array_merge( + [ + 'index' => 'monolog', // Elastic index name + 'type' => 'record', // Elastic document type + 'ignore_error' => false, // Suppress Elastica exceptions + ], + $options + ); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->bulkSend([$record['formatted']]); + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + if ($formatter instanceof ElasticaFormatter) { + return parent::setFormatter($formatter); + } + + throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter'); + } + + /** + * @return mixed[] + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new ElasticaFormatter($this->options['index'], $this->options['type']); + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + $documents = $this->getFormatter()->formatBatch($records); + $this->bulkSend($documents); + } + + /** + * Use Elasticsearch bulk API to send list of documents + * + * @param Document[] $documents + * + * @throws \RuntimeException + */ + protected function bulkSend(array $documents): void + { + try { + $this->client->addDocuments($documents); + } catch (ExceptionInterface $e) { + if (!$this->options['ignore_error']) { + throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e); + } + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php new file mode 100644 index 0000000..e88375c --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Elastic\Elasticsearch\Response\Elasticsearch; +use Throwable; +use RuntimeException; +use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\ElasticsearchFormatter; +use InvalidArgumentException; +use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException; +use Elasticsearch\Client; +use Elastic\Elasticsearch\Exception\InvalidArgumentException as ElasticInvalidArgumentException; +use Elastic\Elasticsearch\Client as Client8; + +/** + * Elasticsearch handler + * + * @link https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html + * + * Simple usage example: + * + * $client = \Elasticsearch\ClientBuilder::create() + * ->setHosts($hosts) + * ->build(); + * + * $options = array( + * 'index' => 'elastic_index_name', + * 'type' => 'elastic_doc_type', + * ); + * $handler = new ElasticsearchHandler($client, $options); + * $log = new Logger('application'); + * $log->pushHandler($handler); + * + * @author Avtandil Kikabidze + */ +class ElasticsearchHandler extends AbstractProcessingHandler +{ + /** + * @var Client|Client8 + */ + protected $client; + + /** + * @var mixed[] Handler config options + */ + protected $options = []; + + /** + * @var bool + */ + private $needsType; + + /** + * @param Client|Client8 $client Elasticsearch Client object + * @param mixed[] $options Handler configuration + */ + public function __construct($client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) + { + if (!$client instanceof Client && !$client instanceof Client8) { + throw new \TypeError('Elasticsearch\Client or Elastic\Elasticsearch\Client instance required'); + } + + parent::__construct($level, $bubble); + $this->client = $client; + $this->options = array_merge( + [ + 'index' => 'monolog', // Elastic index name + 'type' => '_doc', // Elastic document type + 'ignore_error' => false, // Suppress Elasticsearch exceptions + ], + $options + ); + + if ($client instanceof Client8 || $client::VERSION[0] === '7') { + $this->needsType = false; + // force the type to _doc for ES8/ES7 + $this->options['type'] = '_doc'; + } else { + $this->needsType = true; + } + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->bulkSend([$record['formatted']]); + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + if ($formatter instanceof ElasticsearchFormatter) { + return parent::setFormatter($formatter); + } + + throw new InvalidArgumentException('ElasticsearchHandler is only compatible with ElasticsearchFormatter'); + } + + /** + * Getter options + * + * @return mixed[] + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new ElasticsearchFormatter($this->options['index'], $this->options['type']); + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + $documents = $this->getFormatter()->formatBatch($records); + $this->bulkSend($documents); + } + + /** + * Use Elasticsearch bulk API to send list of documents + * + * @param array[] $records Records + _index/_type keys + * @throws \RuntimeException + */ + protected function bulkSend(array $records): void + { + try { + $params = [ + 'body' => [], + ]; + + foreach ($records as $record) { + $params['body'][] = [ + 'index' => $this->needsType ? [ + '_index' => $record['_index'], + '_type' => $record['_type'], + ] : [ + '_index' => $record['_index'], + ], + ]; + unset($record['_index'], $record['_type']); + + $params['body'][] = $record; + } + + /** @var Elasticsearch */ + $responses = $this->client->bulk($params); + + if ($responses['errors'] === true) { + throw $this->createExceptionFromResponses($responses); + } + } catch (Throwable $e) { + if (! $this->options['ignore_error']) { + throw new RuntimeException('Error sending messages to Elasticsearch', 0, $e); + } + } + } + + /** + * Creates elasticsearch exception from responses array + * + * Only the first error is converted into an exception. + * + * @param mixed[]|Elasticsearch $responses returned by $this->client->bulk() + */ + protected function createExceptionFromResponses($responses): Throwable + { + foreach ($responses['items'] ?? [] as $item) { + if (isset($item['index']['error'])) { + return $this->createExceptionFromError($item['index']['error']); + } + } + + if (class_exists(ElasticInvalidArgumentException::class)) { + return new ElasticInvalidArgumentException('Elasticsearch failed to index one or more records.'); + } + + return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.'); + } + + /** + * Creates elasticsearch exception from error array + * + * @param mixed[] $error + */ + protected function createExceptionFromError(array $error): Throwable + { + $previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null; + + if (class_exists(ElasticInvalidArgumentException::class)) { + return new ElasticInvalidArgumentException($error['type'] . ': ' . $error['reason'], 0, $previous); + } + + return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php new file mode 100644 index 0000000..f2e2203 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.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 Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Monolog\Utils; + +/** + * Stores to PHP error_log() handler. + * + * @author Elan Ruusamäe + */ +class ErrorLogHandler extends AbstractProcessingHandler +{ + public const OPERATING_SYSTEM = 0; + public const SAPI = 4; + + /** @var int */ + protected $messageType; + /** @var bool */ + protected $expandNewlines; + + /** + * @param int $messageType Says where the error should go. + * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries + */ + public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false) + { + parent::__construct($level, $bubble); + + if (false === in_array($messageType, self::getAvailableTypes(), true)) { + $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true)); + + throw new \InvalidArgumentException($message); + } + + $this->messageType = $messageType; + $this->expandNewlines = $expandNewlines; + } + + /** + * @return int[] With all available types + */ + public static function getAvailableTypes(): array + { + return [ + self::OPERATING_SYSTEM, + self::SAPI, + ]; + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%'); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if (!$this->expandNewlines) { + error_log((string) $record['formatted'], $this->messageType); + + return; + } + + $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); + if ($lines === false) { + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / '. Utils::pcreLastErrorMessage($pcreErrorCode)); + } + foreach ($lines as $line) { + error_log($line, $this->messageType); + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php new file mode 100644 index 0000000..d4e234c --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.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 Monolog\Handler; + +use Throwable; + +/** + * Forwards records to at most one handler + * + * If a handler fails, the exception is suppressed and the record is forwarded to the next handler. + * + * As soon as one handler handles a record successfully, the handling stops there. + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class FallbackGroupHandler extends GroupHandler +{ + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + foreach ($this->handlers as $handler) { + try { + $handler->handle($record); + break; + } catch (Throwable $e) { + // What throwable? + } + } + + return false === $this->bubble; + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + if ($this->processors) { + $processed = []; + foreach ($records as $record) { + $processed[] = $this->processRecord($record); + } + /** @var Record[] $records */ + $records = $processed; + } + + foreach ($this->handlers as $handler) { + try { + $handler->handleBatch($records); + break; + } catch (Throwable $e) { + // What throwable? + } + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php new file mode 100644 index 0000000..718f17e --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\ResettableInterface; +use Monolog\Formatter\FormatterInterface; +use Psr\Log\LogLevel; + +/** + * Simple handler wrapper that filters records based on a list of levels + * + * It can be configured with an exact list of levels to allow, or a min/max level. + * + * @author Hennadiy Verkh + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface +{ + use ProcessableHandlerTrait; + + /** + * Handler or factory callable($record, $this) + * + * @var callable|HandlerInterface + * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface + */ + protected $handler; + + /** + * Minimum level for logs that are passed to handler + * + * @var int[] + * @phpstan-var array + */ + protected $acceptedLevels; + + /** + * Whether the messages that are handled can bubble up the stack or not + * + * @var bool + */ + protected $bubble; + + /** + * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler + * + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler). + * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided + * @param int|string $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * + * @phpstan-param Level|LevelName|LogLevel::*|array $minLevelOrList + * @phpstan-param Level|LevelName|LogLevel::* $maxLevel + */ + public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true) + { + $this->handler = $handler; + $this->bubble = $bubble; + $this->setAcceptedLevels($minLevelOrList, $maxLevel); + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } + } + + /** + * @phpstan-return array + */ + public function getAcceptedLevels(): array + { + return array_flip($this->acceptedLevels); + } + + /** + * @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided + * @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array + * + * @phpstan-param Level|LevelName|LogLevel::*|array $minLevelOrList + * @phpstan-param Level|LevelName|LogLevel::* $maxLevel + */ + public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY): self + { + if (is_array($minLevelOrList)) { + $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList); + } else { + $minLevelOrList = Logger::toMonologLevel($minLevelOrList); + $maxLevel = Logger::toMonologLevel($maxLevel); + $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { + return $level >= $minLevelOrList && $level <= $maxLevel; + })); + } + $this->acceptedLevels = array_flip($acceptedLevels); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function isHandling(array $record): bool + { + return isset($this->acceptedLevels[$record['level']]); + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if (!$this->isHandling($record)) { + return false; + } + + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + $this->getHandler($record)->handle($record); + + return false === $this->bubble; + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + $filtered = []; + foreach ($records as $record) { + if ($this->isHandling($record)) { + $filtered[] = $record; + } + } + + if (count($filtered) > 0) { + $this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered); + } + } + + /** + * Return the nested handler + * + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface + * + * @phpstan-param Record $record + */ + public function getHandler(array $record = null) + { + if (!$this->handler instanceof HandlerInterface) { + $this->handler = ($this->handler)($record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + return $this->handler; + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + $handler = $this->getHandler(); + if ($handler instanceof FormattableHandlerInterface) { + $handler->setFormatter($formatter); + + return $this; + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + $handler = $this->getHandler(); + if ($handler instanceof FormattableHandlerInterface) { + return $handler->getFormatter(); + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); + } + + public function reset() + { + $this->resetProcessors(); + + if ($this->getHandler() instanceof ResettableInterface) { + $this->getHandler()->reset(); + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php new file mode 100644 index 0000000..0aa5607 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.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 Monolog\Handler\FingersCrossed; + +/** + * Interface for activation strategies for the FingersCrossedHandler. + * + * @author Johannes M. Schmitt + * + * @phpstan-import-type Record from \Monolog\Logger + */ +interface ActivationStrategyInterface +{ + /** + * Returns whether the given record activates the handler. + * + * @phpstan-param Record $record + */ + public function isHandlerActivated(array $record): bool; +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php new file mode 100644 index 0000000..7b9abb5 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.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 Monolog\Handler\FingersCrossed; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Channel and Error level based monolog activation strategy. Allows to trigger activation + * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except + * for records of the 'sql' channel; those should trigger activation on level 'WARN'. + * + * Example: + * + * + * $activationStrategy = new ChannelLevelActivationStrategy( + * Logger::CRITICAL, + * array( + * 'request' => Logger::ALERT, + * 'sensitive' => Logger::ERROR, + * ) + * ); + * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); + * + * + * @author Mike Meessen + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class ChannelLevelActivationStrategy implements ActivationStrategyInterface +{ + /** + * @var Level + */ + private $defaultActionLevel; + + /** + * @var array + */ + private $channelToActionLevel; + + /** + * @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any + * @param array $channelToActionLevel An array that maps channel names to action levels. + * + * @phpstan-param array $channelToActionLevel + * @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel + */ + public function __construct($defaultActionLevel, array $channelToActionLevel = []) + { + $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); + $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); + } + + /** + * @phpstan-param Record $record + */ + public function isHandlerActivated(array $record): bool + { + if (isset($this->channelToActionLevel[$record['channel']])) { + return $record['level'] >= $this->channelToActionLevel[$record['channel']]; + } + + return $record['level'] >= $this->defaultActionLevel; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php new file mode 100644 index 0000000..5ec88ea --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.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 Monolog\Handler\FingersCrossed; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Error level based activation strategy. + * + * @author Johannes M. Schmitt + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class ErrorLevelActivationStrategy implements ActivationStrategyInterface +{ + /** + * @var Level + */ + private $actionLevel; + + /** + * @param int|string $actionLevel Level or name or value + * + * @phpstan-param Level|LevelName|LogLevel::* $actionLevel + */ + public function __construct($actionLevel) + { + $this->actionLevel = Logger::toMonologLevel($actionLevel); + } + + public function isHandlerActivated(array $record): bool + { + return $record['level'] >= $this->actionLevel; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php new file mode 100644 index 0000000..0627b44 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -0,0 +1,252 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; +use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; +use Monolog\Logger; +use Monolog\ResettableInterface; +use Monolog\Formatter\FormatterInterface; +use Psr\Log\LogLevel; + +/** + * Buffers all records until a certain level is reached + * + * The advantage of this approach is that you don't get any clutter in your log files. + * Only requests which actually trigger an error (or whatever your actionLevel is) will be + * in the logs, but they will contain all records, not only those above the level threshold. + * + * You can then have a passthruLevel as well which means that at the end of the request, + * even if it did not get activated, it will still send through log records of e.g. at least a + * warning level. + * + * You can find the various activation strategies in the + * Monolog\Handler\FingersCrossed\ namespace. + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface +{ + use ProcessableHandlerTrait; + + /** + * @var callable|HandlerInterface + * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface + */ + protected $handler; + /** @var ActivationStrategyInterface */ + protected $activationStrategy; + /** @var bool */ + protected $buffering = true; + /** @var int */ + protected $bufferSize; + /** @var Record[] */ + protected $buffer = []; + /** @var bool */ + protected $stopBuffering; + /** + * @var ?int + * @phpstan-var ?Level + */ + protected $passthruLevel; + /** @var bool */ + protected $bubble; + + /** + * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler + * + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler). + * @param int|string|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated + * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true) + * @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered + * + * @phpstan-param Level|LevelName|LogLevel::* $passthruLevel + * @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy + */ + public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null) + { + if (null === $activationStrategy) { + $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING); + } + + // convert simple int activationStrategy to an object + if (!$activationStrategy instanceof ActivationStrategyInterface) { + $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy); + } + + $this->handler = $handler; + $this->activationStrategy = $activationStrategy; + $this->bufferSize = $bufferSize; + $this->bubble = $bubble; + $this->stopBuffering = $stopBuffering; + + if ($passthruLevel !== null) { + $this->passthruLevel = Logger::toMonologLevel($passthruLevel); + } + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } + } + + /** + * {@inheritDoc} + */ + public function isHandling(array $record): bool + { + return true; + } + + /** + * Manually activate this logger regardless of the activation strategy + */ + public function activate(): void + { + if ($this->stopBuffering) { + $this->buffering = false; + } + + $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer); + $this->buffer = []; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + if ($this->buffering) { + $this->buffer[] = $record; + if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { + array_shift($this->buffer); + } + if ($this->activationStrategy->isHandlerActivated($record)) { + $this->activate(); + } + } else { + $this->getHandler($record)->handle($record); + } + + return false === $this->bubble; + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + $this->flushBuffer(); + + $this->getHandler()->close(); + } + + public function reset() + { + $this->flushBuffer(); + + $this->resetProcessors(); + + if ($this->getHandler() instanceof ResettableInterface) { + $this->getHandler()->reset(); + } + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + * + * It also resets the handler to its initial buffering state. + */ + public function clear(): void + { + $this->buffer = []; + $this->reset(); + } + + /** + * Resets the state of the handler. Stops forwarding records to the wrapped handler. + */ + private function flushBuffer(): void + { + if (null !== $this->passthruLevel) { + $level = $this->passthruLevel; + $this->buffer = array_filter($this->buffer, function ($record) use ($level) { + return $record['level'] >= $level; + }); + if (count($this->buffer) > 0) { + $this->getHandler(end($this->buffer))->handleBatch($this->buffer); + } + } + + $this->buffer = []; + $this->buffering = true; + } + + /** + * Return the nested handler + * + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface + * + * @phpstan-param Record $record + */ + public function getHandler(array $record = null) + { + if (!$this->handler instanceof HandlerInterface) { + $this->handler = ($this->handler)($record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + return $this->handler; + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + $handler = $this->getHandler(); + if ($handler instanceof FormattableHandlerInterface) { + $handler->setFormatter($formatter); + + return $this; + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + $handler = $this->getHandler(); + if ($handler instanceof FormattableHandlerInterface) { + return $handler->getFormatter(); + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php new file mode 100644 index 0000000..72718de --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.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 Monolog\Handler; + +use Monolog\Formatter\WildfireFormatter; +use Monolog\Formatter\FormatterInterface; + +/** + * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. + * + * @author Eric Clemmons (@ericclemmons) + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class FirePHPHandler extends AbstractProcessingHandler +{ + use WebRequestRecognizerTrait; + + /** + * WildFire JSON header message format + */ + protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2'; + + /** + * FirePHP structure for parsing messages & their presentation + */ + protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'; + + /** + * Must reference a "known" plugin, otherwise headers won't display in FirePHP + */ + protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3'; + + /** + * Header prefix for Wildfire to recognize & parse headers + */ + protected const HEADER_PREFIX = 'X-Wf'; + + /** + * Whether or not Wildfire vendor-specific headers have been generated & sent yet + * @var bool + */ + protected static $initialized = false; + + /** + * Shared static message index between potentially multiple handlers + * @var int + */ + protected static $messageIndex = 1; + + /** @var bool */ + protected static $sendHeaders = true; + + /** + * Base header creation function used by init headers & record headers + * + * @param array $meta Wildfire Plugin, Protocol & Structure Indexes + * @param string $message Log message + * + * @return array Complete header string ready for the client as key and message as value + * + * @phpstan-return non-empty-array + */ + protected function createHeader(array $meta, string $message): array + { + $header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta)); + + return [$header => $message]; + } + + /** + * Creates message header from record + * + * @return array + * + * @phpstan-return non-empty-array + * + * @see createHeader() + * + * @phpstan-param FormattedRecord $record + */ + protected function createRecordHeader(array $record): array + { + // Wildfire is extensible to support multiple protocols & plugins in a single request, + // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. + return $this->createHeader( + [1, 1, 1, self::$messageIndex++], + $record['formatted'] + ); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new WildfireFormatter(); + } + + /** + * Wildfire initialization headers to enable message parsing + * + * @see createHeader() + * @see sendHeader() + * + * @return array + */ + protected function getInitHeaders(): array + { + // Initial payload consists of required headers for Wildfire + return array_merge( + $this->createHeader(['Protocol', 1], static::PROTOCOL_URI), + $this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI), + $this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI) + ); + } + + /** + * Send header string to the client + */ + protected function sendHeader(string $header, string $content): void + { + if (!headers_sent() && self::$sendHeaders) { + header(sprintf('%s: %s', $header, $content)); + } + } + + /** + * Creates & sends header for a record, ensuring init headers have been sent prior + * + * @see sendHeader() + * @see sendInitHeaders() + */ + protected function write(array $record): void + { + if (!self::$sendHeaders || !$this->isWebRequest()) { + return; + } + + // WildFire-specific headers must be sent prior to any messages + if (!self::$initialized) { + self::$initialized = true; + + self::$sendHeaders = $this->headersAccepted(); + if (!self::$sendHeaders) { + return; + } + + foreach ($this->getInitHeaders() as $header => $content) { + $this->sendHeader($header, $content); + } + } + + $header = $this->createRecordHeader($record); + if (trim(current($header)) !== '') { + $this->sendHeader(key($header), current($header)); + } + } + + /** + * Verifies if the headers are accepted by the current user agent + */ + protected function headersAccepted(): bool + { + if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { + return true; + } + + return isset($_SERVER['HTTP_X_FIREPHP_VERSION']); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php new file mode 100644 index 0000000..85c95b9 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; +use Monolog\Logger; + +/** + * Sends logs to Fleep.io using Webhook integrations + * + * You'll need a Fleep.io account to use this handler. + * + * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation + * @author Ando Roots + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class FleepHookHandler extends SocketHandler +{ + protected const FLEEP_HOST = 'fleep.io'; + + protected const FLEEP_HOOK_URI = '/hook/'; + + /** + * @var string Webhook token (specifies the conversation where logs are sent) + */ + protected $token; + + /** + * Construct a new Fleep.io Handler. + * + * For instructions on how to create a new web hook in your conversations + * see https://fleep.io/integrations/webhooks/ + * + * @param string $token Webhook token + * @throws MissingExtensionException + */ + public function __construct( + string $token, + $level = Logger::DEBUG, + bool $bubble = true, + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler'); + } + + $this->token = $token; + + $connectionString = 'ssl://' . static::FLEEP_HOST . ':443'; + parent::__construct( + $connectionString, + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + } + + /** + * Returns the default formatter to use with this handler + * + * Overloaded to remove empty context and extra arrays from the end of the log message. + * + * @return LineFormatter + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter(null, null, true, true); + } + + /** + * Handles a log record + */ + public function write(array $record): void + { + parent::write($record); + $this->closeSocket(); + } + + /** + * {@inheritDoc} + */ + protected function generateDataStream(array $record): string + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the header of the API Call + */ + private function buildHeader(string $content): string + { + $header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n"; + $header .= "Host: " . static::FLEEP_HOST . "\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * Builds the body of API call + * + * @phpstan-param FormattedRecord $record + */ + private function buildContent(array $record): string + { + $dataArray = [ + 'message' => $record['formatted'], + ]; + + return http_build_query($dataArray); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php new file mode 100644 index 0000000..5715d58 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Formatter\FlowdockFormatter; +use Monolog\Formatter\FormatterInterface; + +/** + * Sends notifications through the Flowdock push API + * + * This must be configured with a FlowdockFormatter instance via setFormatter() + * + * Notes: + * API token - Flowdock API token + * + * @author Dominik Liebler + * @see https://www.flowdock.com/api/push + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 + */ +class FlowdockHandler extends SocketHandler +{ + /** + * @var string + */ + protected $apiToken; + + /** + * @throws MissingExtensionException if OpenSSL is missing + */ + public function __construct( + string $apiToken, + $level = Logger::DEBUG, + bool $bubble = true, + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); + } + + parent::__construct( + 'ssl://api.flowdock.com:443', + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + $this->apiToken = $apiToken; + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + if (!$formatter instanceof FlowdockFormatter) { + throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); + } + + return parent::setFormatter($formatter); + } + + /** + * Gets the default formatter. + */ + protected function getDefaultFormatter(): FormatterInterface + { + throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + parent::write($record); + + $this->closeSocket(); + } + + /** + * {@inheritDoc} + */ + protected function generateDataStream(array $record): string + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @phpstan-param FormattedRecord $record + */ + private function buildContent(array $record): string + { + return Utils::jsonEncode($record['formatted']['flowdock']); + } + + /** + * Builds the header of the API Call + */ + private function buildHeader(string $content): string + { + $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; + $header .= "Host: api.flowdock.com\r\n"; + $header .= "Content-Type: application/json\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php new file mode 100644 index 0000000..fc1693c --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; + +/** + * Interface to describe loggers that have a formatter + * + * @author Jordi Boggiano + */ +interface FormattableHandlerInterface +{ + /** + * Sets the formatter. + * + * @param FormatterInterface $formatter + * @return HandlerInterface self + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface; + + /** + * Gets the formatter. + * + * @return FormatterInterface + */ + public function getFormatter(): FormatterInterface; +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php new file mode 100644 index 0000000..b60bdce --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; + +/** + * Helper trait for implementing FormattableInterface + * + * @author Jordi Boggiano + */ +trait FormattableHandlerTrait +{ + /** + * @var ?FormatterInterface + */ + protected $formatter; + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + $this->formatter = $formatter; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + if (!$this->formatter) { + $this->formatter = $this->getDefaultFormatter(); + } + + return $this->formatter; + } + + /** + * Gets the default formatter. + * + * Overwrite this if the LineFormatter is not a good default for your handler. + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php new file mode 100644 index 0000000..4ff26c4 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.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 Monolog\Handler; + +use Gelf\PublisherInterface; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; +use Monolog\Formatter\FormatterInterface; + +/** + * Handler to send messages to a Graylog2 (http://www.graylog2.org) server + * + * @author Matt Lehner + * @author Benjamin Zikarsky + */ +class GelfHandler extends AbstractProcessingHandler +{ + /** + * @var PublisherInterface the publisher object that sends the message to the server + */ + protected $publisher; + + /** + * @param PublisherInterface $publisher a gelf publisher object + */ + public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true) + { + parent::__construct($level, $bubble); + + $this->publisher = $publisher; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->publisher->publish($record['formatted']); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new GelfMessageFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php new file mode 100644 index 0000000..3c9dc4b --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\ResettableInterface; + +/** + * Forwards records to multiple handlers + * + * @author Lenar Lõhmus + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface +{ + use ProcessableHandlerTrait; + + /** @var HandlerInterface[] */ + protected $handlers; + /** @var bool */ + protected $bubble; + + /** + * @param HandlerInterface[] $handlers Array of Handlers. + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(array $handlers, bool $bubble = true) + { + foreach ($handlers as $handler) { + if (!$handler instanceof HandlerInterface) { + throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); + } + } + + $this->handlers = $handlers; + $this->bubble = $bubble; + } + + /** + * {@inheritDoc} + */ + public function isHandling(array $record): bool + { + foreach ($this->handlers as $handler) { + if ($handler->isHandling($record)) { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + foreach ($this->handlers as $handler) { + $handler->handle($record); + } + + return false === $this->bubble; + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + if ($this->processors) { + $processed = []; + foreach ($records as $record) { + $processed[] = $this->processRecord($record); + } + /** @var Record[] $records */ + $records = $processed; + } + + foreach ($this->handlers as $handler) { + $handler->handleBatch($records); + } + } + + public function reset() + { + $this->resetProcessors(); + + foreach ($this->handlers as $handler) { + if ($handler instanceof ResettableInterface) { + $handler->reset(); + } + } + } + + public function close(): void + { + parent::close(); + + foreach ($this->handlers as $handler) { + $handler->close(); + } + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + foreach ($this->handlers as $handler) { + if ($handler instanceof FormattableHandlerInterface) { + $handler->setFormatter($formatter); + } + } + + return $this; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/Handler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/Handler.php new file mode 100644 index 0000000..34b4935 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/Handler.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 Monolog\Handler; + +/** + * Base Handler class providing basic close() support as well as handleBatch + * + * @author Jordi Boggiano + */ +abstract class Handler implements HandlerInterface +{ + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + foreach ($records as $record) { + $this->handle($record); + } + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + } + + public function __destruct() + { + try { + $this->close(); + } catch (\Throwable $e) { + // do nothing + } + } + + public function __sleep() + { + $this->close(); + + $reflClass = new \ReflectionClass($this); + + $keys = []; + foreach ($reflClass->getProperties() as $reflProp) { + if (!$reflProp->isStatic()) { + $keys[] = $reflProp->getName(); + } + } + + return $keys; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php new file mode 100644 index 0000000..affcc51 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.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 Monolog\Handler; + +/** + * Interface that all Monolog Handlers must implement + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + */ +interface HandlerInterface +{ + /** + * Checks whether the given record will be handled by this handler. + * + * This is mostly done for performance reasons, to avoid calling processors for nothing. + * + * Handlers should still check the record levels within handle(), returning false in isHandling() + * is no guarantee that handle() will not be called, and isHandling() might not be called + * for a given record. + * + * @param array $record Partial log record containing only a level key + * + * @return bool + * + * @phpstan-param array{level: Level} $record + */ + public function isHandling(array $record): bool; + + /** + * Handles a record. + * + * All records may be passed to this method, and the handler should discard + * those that it does not want to handle. + * + * The return value of this function controls the bubbling process of the handler stack. + * Unless the bubbling is interrupted (by returning true), the Logger class will keep on + * calling further handlers in the stack with a given log record. + * + * @param array $record The record to handle + * @return bool true means that this handler handled the record, and that bubbling is not permitted. + * false means the record was either not processed or that this handler allows bubbling. + * + * @phpstan-param Record $record + */ + public function handle(array $record): bool; + + /** + * Handles a set of records at once. + * + * @param array $records The records to handle (an array of record arrays) + * + * @phpstan-param Record[] $records + */ + public function handleBatch(array $records): void; + + /** + * Closes the handler. + * + * Ends a log cycle and frees all resources used by the handler. + * + * Closing a Handler means flushing all buffers and freeing any open resources/handles. + * + * Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage) + * and ideally handlers should be able to reopen themselves on handle() after they have been closed. + * + * This is useful at the end of a request and will be called automatically when the object + * is destroyed if you extend Monolog\Handler\Handler. + * + * If you are thinking of calling this method yourself, most likely you should be + * calling ResettableInterface::reset instead. Have a look. + */ + public function close(): void; +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php new file mode 100644 index 0000000..d4351b9 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\ResettableInterface; +use Monolog\Formatter\FormatterInterface; + +/** + * This simple wrapper class can be used to extend handlers functionality. + * + * Example: A custom filtering that can be applied to any handler. + * + * Inherit from this class and override handle() like this: + * + * public function handle(array $record) + * { + * if ($record meets certain conditions) { + * return false; + * } + * return $this->handler->handle($record); + * } + * + * @author Alexey Karapetov + */ +class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface +{ + /** + * @var HandlerInterface + */ + protected $handler; + + public function __construct(HandlerInterface $handler) + { + $this->handler = $handler; + } + + /** + * {@inheritDoc} + */ + public function isHandling(array $record): bool + { + return $this->handler->isHandling($record); + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + return $this->handler->handle($record); + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + $this->handler->handleBatch($records); + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + $this->handler->close(); + } + + /** + * {@inheritDoc} + */ + public function pushProcessor(callable $callback): HandlerInterface + { + if ($this->handler instanceof ProcessableHandlerInterface) { + $this->handler->pushProcessor($callback); + + return $this; + } + + throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class); + } + + /** + * {@inheritDoc} + */ + public function popProcessor(): callable + { + if ($this->handler instanceof ProcessableHandlerInterface) { + return $this->handler->popProcessor(); + } + + throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class); + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + if ($this->handler instanceof FormattableHandlerInterface) { + $this->handler->setFormatter($formatter); + + return $this; + } + + throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + if ($this->handler instanceof FormattableHandlerInterface) { + return $this->handler->getFormatter(); + } + + throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); + } + + public function reset() + { + if ($this->handler instanceof ResettableInterface) { + $this->handler->reset(); + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php new file mode 100644 index 0000000..000ccea --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; + +/** + * IFTTTHandler uses cURL to trigger IFTTT Maker actions + * + * Register a secret key and trigger/event name at https://ifttt.com/maker + * + * value1 will be the channel from monolog's Logger constructor, + * value2 will be the level name (ERROR, WARNING, ..) + * value3 will be the log record's message + * + * @author Nehal Patel + */ +class IFTTTHandler extends AbstractProcessingHandler +{ + /** @var string */ + private $eventName; + /** @var string */ + private $secretKey; + + /** + * @param string $eventName The name of the IFTTT Maker event that should be triggered + * @param string $secretKey A valid IFTTT secret key + */ + public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true) + { + if (!extension_loaded('curl')) { + throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler'); + } + + $this->eventName = $eventName; + $this->secretKey = $secretKey; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + public function write(array $record): void + { + $postData = [ + "value1" => $record["channel"], + "value2" => $record["level_name"], + "value3" => $record["message"], + ]; + $postString = Utils::jsonEncode($postData); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $postString); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type: application/json", + ]); + + Curl\Util::execute($ch); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php new file mode 100644 index 0000000..71f64a2 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.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 Monolog\Handler; + +use Monolog\Logger; + +/** + * Inspired on LogEntriesHandler. + * + * @author Robert Kaufmann III + * @author Gabriel Machado + */ +class InsightOpsHandler extends SocketHandler +{ + /** + * @var string + */ + protected $logToken; + + /** + * @param string $token Log token supplied by InsightOps + * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'. + * @param bool $useSSL Whether or not SSL encryption should be used + * + * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing + */ + public function __construct( + string $token, + string $region = 'us', + bool $useSSL = true, + $level = Logger::DEBUG, + bool $bubble = true, + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + if ($useSSL && !extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler'); + } + + $endpoint = $useSSL + ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' + : $region . '.data.logs.insight.rapid7.com:80'; + + parent::__construct( + $endpoint, + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + $this->logToken = $token; + } + + /** + * {@inheritDoc} + */ + protected function generateDataStream(array $record): string + { + return $this->logToken . ' ' . $record['formatted']; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php new file mode 100644 index 0000000..25fcd15 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.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 Monolog\Handler; + +use Monolog\Logger; + +/** + * @author Robert Kaufmann III + */ +class LogEntriesHandler extends SocketHandler +{ + /** + * @var string + */ + protected $logToken; + + /** + * @param string $token Log token supplied by LogEntries + * @param bool $useSSL Whether or not SSL encryption should be used. + * @param string $host Custom hostname to send the data to if needed + * + * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing + */ + public function __construct( + string $token, + bool $useSSL = true, + $level = Logger::DEBUG, + bool $bubble = true, + string $host = 'data.logentries.com', + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + if ($useSSL && !extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); + } + + $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80'; + parent::__construct( + $endpoint, + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + $this->logToken = $token; + } + + /** + * {@inheritDoc} + */ + protected function generateDataStream(array $record): string + { + return $this->logToken . ' ' . $record['formatted']; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php new file mode 100644 index 0000000..6d13db3 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LogglyFormatter; +use function array_key_exists; +use CurlHandle; + +/** + * Sends errors to Loggly. + * + * @author Przemek Sobstel + * @author Adam Pancutt + * @author Gregory Barchard + */ +class LogglyHandler extends AbstractProcessingHandler +{ + protected const HOST = 'logs-01.loggly.com'; + protected const ENDPOINT_SINGLE = 'inputs'; + protected const ENDPOINT_BATCH = 'bulk'; + + /** + * Caches the curl handlers for every given endpoint. + * + * @var resource[]|CurlHandle[] + */ + protected $curlHandlers = []; + + /** @var string */ + protected $token; + + /** @var string[] */ + protected $tag = []; + + /** + * @param string $token API token supplied by Loggly + * + * @throws MissingExtensionException If the curl extension is missing + */ + public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true) + { + if (!extension_loaded('curl')) { + throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler'); + } + + $this->token = $token; + + parent::__construct($level, $bubble); + } + + /** + * Loads and returns the shared curl handler for the given endpoint. + * + * @param string $endpoint + * + * @return resource|CurlHandle + */ + protected function getCurlHandler(string $endpoint) + { + if (!array_key_exists($endpoint, $this->curlHandlers)) { + $this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint); + } + + return $this->curlHandlers[$endpoint]; + } + + /** + * Starts a fresh curl session for the given endpoint and returns its handler. + * + * @param string $endpoint + * + * @return resource|CurlHandle + */ + private function loadCurlHandle(string $endpoint) + { + $url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token); + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + return $ch; + } + + /** + * @param string[]|string $tag + */ + public function setTag($tag): self + { + $tag = !empty($tag) ? $tag : []; + $this->tag = is_array($tag) ? $tag : [$tag]; + + return $this; + } + + /** + * @param string[]|string $tag + */ + public function addTag($tag): self + { + if (!empty($tag)) { + $tag = is_array($tag) ? $tag : [$tag]; + $this->tag = array_unique(array_merge($this->tag, $tag)); + } + + return $this; + } + + protected function write(array $record): void + { + $this->send($record["formatted"], static::ENDPOINT_SINGLE); + } + + public function handleBatch(array $records): void + { + $level = $this->level; + + $records = array_filter($records, function ($record) use ($level) { + return ($record['level'] >= $level); + }); + + if ($records) { + $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH); + } + } + + protected function send(string $data, string $endpoint): void + { + $ch = $this->getCurlHandler($endpoint); + + $headers = ['Content-Type: application/json']; + + if (!empty($this->tag)) { + $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag); + } + + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + Curl\Util::execute($ch, 5, false); + } + + protected function getDefaultFormatter(): FormatterInterface + { + return new LogglyFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php new file mode 100644 index 0000000..859a469 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LogmaticFormatter; + +/** + * @author Julien Breux + */ +class LogmaticHandler extends SocketHandler +{ + /** + * @var string + */ + private $logToken; + + /** + * @var string + */ + private $hostname; + + /** + * @var string + */ + private $appname; + + /** + * @param string $token Log token supplied by Logmatic. + * @param string $hostname Host name supplied by Logmatic. + * @param string $appname Application name supplied by Logmatic. + * @param bool $useSSL Whether or not SSL encryption should be used. + * + * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing + */ + public function __construct( + string $token, + string $hostname = '', + string $appname = '', + bool $useSSL = true, + $level = Logger::DEBUG, + bool $bubble = true, + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + if ($useSSL && !extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler'); + } + + $endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514'; + $endpoint .= '/v1/'; + + parent::__construct( + $endpoint, + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + + $this->logToken = $token; + $this->hostname = $hostname; + $this->appname = $appname; + } + + /** + * {@inheritDoc} + */ + protected function generateDataStream(array $record): string + { + return $this->logToken . ' ' . $record['formatted']; + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + $formatter = new LogmaticFormatter(); + + if (!empty($this->hostname)) { + $formatter->setHostname($this->hostname); + } + if (!empty($this->appname)) { + $formatter->setAppname($this->appname); + } + + return $formatter; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php new file mode 100644 index 0000000..97f3432 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\HtmlFormatter; + +/** + * Base class for all mail handlers + * + * @author Gyula Sallai + * + * @phpstan-import-type Record from \Monolog\Logger + */ +abstract class MailHandler extends AbstractProcessingHandler +{ + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + $messages = []; + + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + /** @var Record $message */ + $message = $this->processRecord($record); + $messages[] = $message; + } + + if (!empty($messages)) { + $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); + } + } + + /** + * Send a mail with the given content + * + * @param string $content formatted email body to be sent + * @param array $records the array of log records that formed this content + * + * @phpstan-param Record[] $records + */ + abstract protected function send(string $content, array $records): void; + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->send((string) $record['formatted'], [$record]); + } + + /** + * @phpstan-param non-empty-array $records + * @phpstan-return Record + */ + protected function getHighestRecord(array $records): array + { + $highestRecord = null; + foreach ($records as $record) { + if ($highestRecord === null || $highestRecord['level'] < $record['level']) { + $highestRecord = $record; + } + } + + return $highestRecord; + } + + protected function isHtmlBody(string $body): bool + { + return ($body[0] ?? null) === '<'; + } + + /** + * Gets the default formatter. + * + * @return FormatterInterface + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new HtmlFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php new file mode 100644 index 0000000..3003500 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Swift; +use Swift_Message; + +/** + * MandrillHandler uses cURL to send the emails to the Mandrill API + * + * @author Adam Nicholson + */ +class MandrillHandler extends MailHandler +{ + /** @var Swift_Message */ + protected $message; + /** @var string */ + protected $apiKey; + + /** + * @psalm-param Swift_Message|callable(): Swift_Message $message + * + * @param string $apiKey A valid Mandrill API key + * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced + */ + public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true) + { + parent::__construct($level, $bubble); + + if (!$message instanceof Swift_Message && is_callable($message)) { + $message = $message(); + } + if (!$message instanceof Swift_Message) { + throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); + } + $this->message = $message; + $this->apiKey = $apiKey; + } + + /** + * {@inheritDoc} + */ + protected function send(string $content, array $records): void + { + $mime = 'text/plain'; + if ($this->isHtmlBody($content)) { + $mime = 'text/html'; + } + + $message = clone $this->message; + $message->setBody($content, $mime); + /** @phpstan-ignore-next-line */ + if (version_compare(Swift::VERSION, '6.0.0', '>=')) { + $message->setDate(new \DateTimeImmutable()); + } else { + /** @phpstan-ignore-next-line */ + $message->setDate(time()); + } + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json'); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ + 'key' => $this->apiKey, + 'raw_message' => (string) $message, + 'async' => false, + ])); + + Curl\Util::execute($ch); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php new file mode 100644 index 0000000..3965aee --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.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 Monolog\Handler; + +/** + * Exception can be thrown if an extension for a handler is missing + * + * @author Christian Bergau + */ +class MissingExtensionException extends \Exception +{ +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php new file mode 100644 index 0000000..3063091 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.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 Monolog\Handler; + +use MongoDB\Driver\BulkWrite; +use MongoDB\Driver\Manager; +use MongoDB\Client; +use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\MongoDBFormatter; + +/** + * Logs to a MongoDB database. + * + * Usage example: + * + * $log = new \Monolog\Logger('application'); + * $client = new \MongoDB\Client('mongodb://localhost:27017'); + * $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod'); + * $log->pushHandler($mongodb); + * + * The above examples uses the MongoDB PHP library's client class; however, the + * MongoDB\Driver\Manager class from ext-mongodb is also supported. + */ +class MongoDBHandler extends AbstractProcessingHandler +{ + /** @var \MongoDB\Collection */ + private $collection; + /** @var Client|Manager */ + private $manager; + /** @var string */ + private $namespace; + + /** + * Constructor. + * + * @param Client|Manager $mongodb MongoDB library or driver client + * @param string $database Database name + * @param string $collection Collection name + */ + public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true) + { + if (!($mongodb instanceof Client || $mongodb instanceof Manager)) { + throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required'); + } + + if ($mongodb instanceof Client) { + $this->collection = $mongodb->selectCollection($database, $collection); + } else { + $this->manager = $mongodb; + $this->namespace = $database . '.' . $collection; + } + + parent::__construct($level, $bubble); + } + + protected function write(array $record): void + { + if (isset($this->collection)) { + $this->collection->insertOne($record['formatted']); + } + + if (isset($this->manager, $this->namespace)) { + $bulk = new BulkWrite; + $bulk->insert($record["formatted"]); + $this->manager->executeBulkWrite($this->namespace, $bulk); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new MongoDBFormatter; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php new file mode 100644 index 0000000..0c0a3bd --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * NativeMailerHandler uses the mail() function to send the emails + * + * @author Christophe Coevoet + * @author Mark Garrett + */ +class NativeMailerHandler extends MailHandler +{ + /** + * The email addresses to which the message will be sent + * @var string[] + */ + protected $to; + + /** + * The subject of the email + * @var string + */ + protected $subject; + + /** + * Optional headers for the message + * @var string[] + */ + protected $headers = []; + + /** + * Optional parameters for the message + * @var string[] + */ + protected $parameters = []; + + /** + * The wordwrap length for the message + * @var int + */ + protected $maxColumnWidth; + + /** + * The Content-type for the message + * @var string|null + */ + protected $contentType; + + /** + * The encoding for the message + * @var string + */ + protected $encoding = 'utf-8'; + + /** + * @param string|string[] $to The receiver of the mail + * @param string $subject The subject of the mail + * @param string $from The sender of the mail + * @param int $maxColumnWidth The maximum column width that the message lines will have + */ + public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70) + { + parent::__construct($level, $bubble); + $this->to = (array) $to; + $this->subject = $subject; + $this->addHeader(sprintf('From: %s', $from)); + $this->maxColumnWidth = $maxColumnWidth; + } + + /** + * Add headers to the message + * + * @param string|string[] $headers Custom added headers + */ + public function addHeader($headers): self + { + foreach ((array) $headers as $header) { + if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) { + throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons'); + } + $this->headers[] = $header; + } + + return $this; + } + + /** + * Add parameters to the message + * + * @param string|string[] $parameters Custom added parameters + */ + public function addParameter($parameters): self + { + $this->parameters = array_merge($this->parameters, (array) $parameters); + + return $this; + } + + /** + * {@inheritDoc} + */ + protected function send(string $content, array $records): void + { + $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain'); + + if ($contentType !== 'text/html') { + $content = wordwrap($content, $this->maxColumnWidth); + } + + $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n"); + $headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n"; + if ($contentType === 'text/html' && false === strpos($headers, 'MIME-Version:')) { + $headers .= 'MIME-Version: 1.0' . "\r\n"; + } + + $subject = $this->subject; + if ($records) { + $subjectFormatter = new LineFormatter($this->subject); + $subject = $subjectFormatter->format($this->getHighestRecord($records)); + } + + $parameters = implode(' ', $this->parameters); + foreach ($this->to as $to) { + mail($to, $subject, $content, $headers, $parameters); + } + } + + public function getContentType(): ?string + { + return $this->contentType; + } + + public function getEncoding(): string + { + return $this->encoding; + } + + /** + * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages. + */ + public function setContentType(string $contentType): self + { + if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) { + throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); + } + + $this->contentType = $contentType; + + return $this; + } + + public function setEncoding(string $encoding): self + { + if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) { + throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection'); + } + + $this->encoding = $encoding; + + return $this; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php new file mode 100644 index 0000000..114d749 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php @@ -0,0 +1,199 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Formatter\NormalizerFormatter; +use Monolog\Formatter\FormatterInterface; + +/** + * Class to record a log on a NewRelic application. + * Enabling New Relic High Security mode may prevent capture of useful information. + * + * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted'] + * + * @see https://docs.newrelic.com/docs/agents/php-agent + * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security + */ +class NewRelicHandler extends AbstractProcessingHandler +{ + /** + * Name of the New Relic application that will receive logs from this handler. + * + * @var ?string + */ + protected $appName; + + /** + * Name of the current transaction + * + * @var ?string + */ + protected $transactionName; + + /** + * Some context and extra data is passed into the handler as arrays of values. Do we send them as is + * (useful if we are using the API), or explode them for display on the NewRelic RPM website? + * + * @var bool + */ + protected $explodeArrays; + + /** + * {@inheritDoc} + * + * @param string|null $appName + * @param bool $explodeArrays + * @param string|null $transactionName + */ + public function __construct( + $level = Logger::ERROR, + bool $bubble = true, + ?string $appName = null, + bool $explodeArrays = false, + ?string $transactionName = null + ) { + parent::__construct($level, $bubble); + + $this->appName = $appName; + $this->explodeArrays = $explodeArrays; + $this->transactionName = $transactionName; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if (!$this->isNewRelicEnabled()) { + throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); + } + + if ($appName = $this->getAppName($record['context'])) { + $this->setNewRelicAppName($appName); + } + + if ($transactionName = $this->getTransactionName($record['context'])) { + $this->setNewRelicTransactionName($transactionName); + unset($record['formatted']['context']['transaction_name']); + } + + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) { + newrelic_notice_error($record['message'], $record['context']['exception']); + unset($record['formatted']['context']['exception']); + } else { + newrelic_notice_error($record['message']); + } + + if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) { + foreach ($record['formatted']['context'] as $key => $parameter) { + if (is_array($parameter) && $this->explodeArrays) { + foreach ($parameter as $paramKey => $paramValue) { + $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue); + } + } else { + $this->setNewRelicParameter('context_' . $key, $parameter); + } + } + } + + if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) { + foreach ($record['formatted']['extra'] as $key => $parameter) { + if (is_array($parameter) && $this->explodeArrays) { + foreach ($parameter as $paramKey => $paramValue) { + $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue); + } + } else { + $this->setNewRelicParameter('extra_' . $key, $parameter); + } + } + } + } + + /** + * Checks whether the NewRelic extension is enabled in the system. + * + * @return bool + */ + protected function isNewRelicEnabled(): bool + { + return extension_loaded('newrelic'); + } + + /** + * Returns the appname where this log should be sent. Each log can override the default appname, set in this + * handler's constructor, by providing the appname in it's context. + * + * @param mixed[] $context + */ + protected function getAppName(array $context): ?string + { + if (isset($context['appname'])) { + return $context['appname']; + } + + return $this->appName; + } + + /** + * Returns the name of the current transaction. Each log can override the default transaction name, set in this + * handler's constructor, by providing the transaction_name in it's context + * + * @param mixed[] $context + */ + protected function getTransactionName(array $context): ?string + { + if (isset($context['transaction_name'])) { + return $context['transaction_name']; + } + + return $this->transactionName; + } + + /** + * Sets the NewRelic application that should receive this log. + */ + protected function setNewRelicAppName(string $appName): void + { + newrelic_set_appname($appName); + } + + /** + * Overwrites the name of the current transaction + */ + protected function setNewRelicTransactionName(string $transactionName): void + { + newrelic_name_transaction($transactionName); + } + + /** + * @param string $key + * @param mixed $value + */ + protected function setNewRelicParameter(string $key, $value): void + { + if (null === $value || is_scalar($value)) { + newrelic_add_custom_parameter($key, $value); + } else { + newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true)); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new NormalizerFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php new file mode 100644 index 0000000..1ddf0be --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.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 Monolog\Handler; + +/** + * No-op + * + * This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack. + * This can be used for testing, or to disable a handler when overriding a configuration without + * influencing the rest of the stack. + * + * @author Roel Harbers + */ +class NoopHandler extends Handler +{ + /** + * {@inheritDoc} + */ + public function isHandling(array $record): bool + { + return true; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + return false; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php new file mode 100644 index 0000000..e75ee0c --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Blackhole + * + * Any record it can handle will be thrown away. This can be used + * to put on top of an existing stack to override it temporarily. + * + * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class NullHandler extends Handler +{ + /** + * @var int + */ + private $level; + + /** + * @param string|int $level The minimum logging level at which this handler will be triggered + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function __construct($level = Logger::DEBUG) + { + $this->level = Logger::toMonologLevel($level); + } + + /** + * {@inheritDoc} + */ + public function isHandling(array $record): bool + { + return $record['level'] >= $this->level; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + return $record['level'] >= $this->level; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php new file mode 100644 index 0000000..22068c9 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; + +/** + * Handler to only pass log messages when a certain threshold of number of messages is reached. + * + * This can be useful in cases of processing a batch of data, but you're for example only interested + * in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right? + * + * Usage example: + * + * ``` + * $log = new Logger('application'); + * $handler = new SomeHandler(...) + * + * // Pass all warnings to the handler when more than 10 & all error messages when more then 5 + * $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]); + * + * $log->pushHandler($overflow); + *``` + * + * @author Kris Buist + */ +class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface +{ + /** @var HandlerInterface */ + private $handler; + + /** @var int[] */ + private $thresholdMap = [ + Logger::DEBUG => 0, + Logger::INFO => 0, + Logger::NOTICE => 0, + Logger::WARNING => 0, + Logger::ERROR => 0, + Logger::CRITICAL => 0, + Logger::ALERT => 0, + Logger::EMERGENCY => 0, + ]; + + /** + * Buffer of all messages passed to the handler before the threshold was reached + * + * @var mixed[][] + */ + private $buffer = []; + + /** + * @param HandlerInterface $handler + * @param int[] $thresholdMap Dictionary of logger level => threshold + */ + public function __construct( + HandlerInterface $handler, + array $thresholdMap = [], + $level = Logger::DEBUG, + bool $bubble = true + ) { + $this->handler = $handler; + foreach ($thresholdMap as $thresholdLevel => $threshold) { + $this->thresholdMap[$thresholdLevel] = $threshold; + } + parent::__construct($level, $bubble); + } + + /** + * Handles a record. + * + * All records may be passed to this method, and the handler should discard + * those that it does not want to handle. + * + * The return value of this function controls the bubbling process of the handler stack. + * Unless the bubbling is interrupted (by returning true), the Logger class will keep on + * calling further handlers in the stack with a given log record. + * + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if ($record['level'] < $this->level) { + return false; + } + + $level = $record['level']; + + if (!isset($this->thresholdMap[$level])) { + $this->thresholdMap[$level] = 0; + } + + if ($this->thresholdMap[$level] > 0) { + // The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1 + $this->thresholdMap[$level]--; + $this->buffer[$level][] = $record; + + return false === $this->bubble; + } + + if ($this->thresholdMap[$level] == 0) { + // This current message is breaking the threshold. Flush the buffer and continue handling the current record + foreach ($this->buffer[$level] ?? [] as $buffered) { + $this->handler->handle($buffered); + } + $this->thresholdMap[$level]--; + unset($this->buffer[$level]); + } + + $this->handler->handle($record); + + return false === $this->bubble; + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + if ($this->handler instanceof FormattableHandlerInterface) { + $this->handler->setFormatter($formatter); + + return $this; + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + if ($this->handler instanceof FormattableHandlerInterface) { + return $this->handler->getFormatter(); + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php new file mode 100644 index 0000000..23a1d11 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php @@ -0,0 +1,263 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Monolog\Utils; +use PhpConsole\Connector; +use PhpConsole\Handler as VendorPhpConsoleHandler; +use PhpConsole\Helper; + +/** + * Monolog handler for Google Chrome extension "PHP Console" + * + * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely + * + * Usage: + * 1. Install Google Chrome extension [now dead and removed from the chrome store] + * 2. See overview https://github.com/barbushin/php-console#overview + * 3. Install PHP Console library https://github.com/barbushin/php-console#installation + * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png) + * + * $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler())); + * \Monolog\ErrorHandler::register($logger); + * echo $undefinedVar; + * $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012)); + * PC::debug($_SERVER); // PHP Console debugger for any type of vars + * + * @author Sergey Barbushin https://www.linkedin.com/in/barbushin + * + * @phpstan-import-type Record from \Monolog\Logger + * @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4 + */ +class PHPConsoleHandler extends AbstractProcessingHandler +{ + /** @var array */ + private $options = [ + 'enabled' => true, // bool Is PHP Console server enabled + 'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with... + 'debugTagsKeysInContext' => [0, 'tag'], // bool Is PHP Console server enabled + 'useOwnErrorsHandler' => false, // bool Enable errors handling + 'useOwnExceptionsHandler' => false, // bool Enable exceptions handling + 'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths + 'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s') + 'serverEncoding' => null, // string|null Server internal encoding + 'headersLimit' => null, // int|null Set headers size limit for your web-server + 'password' => null, // string|null Protect PHP Console connection by password + 'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed + 'ipMasks' => [], // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1') + 'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required) + 'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings + 'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level + 'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number + 'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item + 'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON + 'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug + 'dataStorage' => null, // \PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ) + ]; + + /** @var Connector */ + private $connector; + + /** + * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details + * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional) + * @throws \RuntimeException + */ + public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true) + { + if (!class_exists('PhpConsole\Connector')) { + throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation'); + } + parent::__construct($level, $bubble); + $this->options = $this->initOptions($options); + $this->connector = $this->initConnector($connector); + } + + /** + * @param array $options + * + * @return array + */ + private function initOptions(array $options): array + { + $wrongOptions = array_diff(array_keys($options), array_keys($this->options)); + if ($wrongOptions) { + throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions)); + } + + return array_replace($this->options, $options); + } + + private function initConnector(?Connector $connector = null): Connector + { + if (!$connector) { + if ($this->options['dataStorage']) { + Connector::setPostponeStorage($this->options['dataStorage']); + } + $connector = Connector::getInstance(); + } + + if ($this->options['registerHelper'] && !Helper::isRegistered()) { + Helper::register(); + } + + if ($this->options['enabled'] && $connector->isActiveClient()) { + if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) { + $handler = VendorPhpConsoleHandler::getInstance(); + $handler->setHandleErrors($this->options['useOwnErrorsHandler']); + $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']); + $handler->start(); + } + if ($this->options['sourcesBasePath']) { + $connector->setSourcesBasePath($this->options['sourcesBasePath']); + } + if ($this->options['serverEncoding']) { + $connector->setServerEncoding($this->options['serverEncoding']); + } + if ($this->options['password']) { + $connector->setPassword($this->options['password']); + } + if ($this->options['enableSslOnlyMode']) { + $connector->enableSslOnlyMode(); + } + if ($this->options['ipMasks']) { + $connector->setAllowedIpMasks($this->options['ipMasks']); + } + if ($this->options['headersLimit']) { + $connector->setHeadersLimit($this->options['headersLimit']); + } + if ($this->options['detectDumpTraceAndSource']) { + $connector->getDebugDispatcher()->detectTraceAndSource = true; + } + $dumper = $connector->getDumper(); + $dumper->levelLimit = $this->options['dumperLevelLimit']; + $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit']; + $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit']; + $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit']; + $dumper->detectCallbacks = $this->options['dumperDetectCallbacks']; + if ($this->options['enableEvalListener']) { + $connector->startEvalRequestsListener(); + } + } + + return $connector; + } + + public function getConnector(): Connector + { + return $this->connector; + } + + /** + * @return array + */ + public function getOptions(): array + { + return $this->options; + } + + public function handle(array $record): bool + { + if ($this->options['enabled'] && $this->connector->isActiveClient()) { + return parent::handle($record); + } + + return !$this->bubble; + } + + /** + * Writes the record down to the log of the implementing handler + */ + protected function write(array $record): void + { + if ($record['level'] < Logger::NOTICE) { + $this->handleDebugRecord($record); + } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) { + $this->handleExceptionRecord($record); + } else { + $this->handleErrorRecord($record); + } + } + + /** + * @phpstan-param Record $record + */ + private function handleDebugRecord(array $record): void + { + $tags = $this->getRecordTags($record); + $message = $record['message']; + if ($record['context']) { + $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true); + } + $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']); + } + + /** + * @phpstan-param Record $record + */ + private function handleExceptionRecord(array $record): void + { + $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']); + } + + /** + * @phpstan-param Record $record + */ + private function handleErrorRecord(array $record): void + { + $context = $record['context']; + + $this->connector->getErrorsDispatcher()->dispatchError( + $context['code'] ?? null, + $context['message'] ?? $record['message'], + $context['file'] ?? null, + $context['line'] ?? null, + $this->options['classesPartialsTraceIgnore'] + ); + } + + /** + * @phpstan-param Record $record + * @return string + */ + private function getRecordTags(array &$record) + { + $tags = null; + if (!empty($record['context'])) { + $context = & $record['context']; + foreach ($this->options['debugTagsKeysInContext'] as $key) { + if (!empty($context[$key])) { + $tags = $context[$key]; + if ($key === 0) { + array_shift($context); + } else { + unset($context[$key]); + } + break; + } + } + } + + return $tags ?: strtolower($record['level_name']); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter('%message%'); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php new file mode 100644 index 0000000..8a8cf1b --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.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 Monolog\Handler; + +use Monolog\Logger; + +/** + * Stores to STDIN of any process, specified by a command. + * + * Usage example: + *
+ * $log = new Logger('myLogger');
+ * $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
+ * 
+ * + * @author Kolja Zuelsdorf + */ +class ProcessHandler extends AbstractProcessingHandler +{ + /** + * Holds the process to receive data on its STDIN. + * + * @var resource|bool|null + */ + private $process; + + /** + * @var string + */ + private $command; + + /** + * @var string|null + */ + private $cwd; + + /** + * @var resource[] + */ + private $pipes = []; + + /** + * @var array + */ + protected const DESCRIPTOR_SPEC = [ + 0 => ['pipe', 'r'], // STDIN is a pipe that the child will read from + 1 => ['pipe', 'w'], // STDOUT is a pipe that the child will write to + 2 => ['pipe', 'w'], // STDERR is a pipe to catch the any errors + ]; + + /** + * @param string $command Command for the process to start. Absolute paths are recommended, + * especially if you do not use the $cwd parameter. + * @param string|null $cwd "Current working directory" (CWD) for the process to be executed in. + * @throws \InvalidArgumentException + */ + public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null) + { + if ($command === '') { + throw new \InvalidArgumentException('The command argument must be a non-empty string.'); + } + if ($cwd === '') { + throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.'); + } + + parent::__construct($level, $bubble); + + $this->command = $command; + $this->cwd = $cwd; + } + + /** + * Writes the record down to the log of the implementing handler + * + * @throws \UnexpectedValueException + */ + protected function write(array $record): void + { + $this->ensureProcessIsStarted(); + + $this->writeProcessInput($record['formatted']); + + $errors = $this->readProcessErrors(); + if (empty($errors) === false) { + throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors)); + } + } + + /** + * Makes sure that the process is actually started, and if not, starts it, + * assigns the stream pipes, and handles startup errors, if any. + */ + private function ensureProcessIsStarted(): void + { + if (is_resource($this->process) === false) { + $this->startProcess(); + + $this->handleStartupErrors(); + } + } + + /** + * Starts the actual process and sets all streams to non-blocking. + */ + private function startProcess(): void + { + $this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd); + + foreach ($this->pipes as $pipe) { + stream_set_blocking($pipe, false); + } + } + + /** + * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any. + * + * @throws \UnexpectedValueException + */ + private function handleStartupErrors(): void + { + $selected = $this->selectErrorStream(); + if (false === $selected) { + throw new \UnexpectedValueException('Something went wrong while selecting a stream.'); + } + + $errors = $this->readProcessErrors(); + + if (is_resource($this->process) === false || empty($errors) === false) { + throw new \UnexpectedValueException( + sprintf('The process "%s" could not be opened: ' . $errors, $this->command) + ); + } + } + + /** + * Selects the STDERR stream. + * + * @return int|bool + */ + protected function selectErrorStream() + { + $empty = []; + $errorPipes = [$this->pipes[2]]; + + return stream_select($errorPipes, $empty, $empty, 1); + } + + /** + * Reads the errors of the process, if there are any. + * + * @codeCoverageIgnore + * @return string Empty string if there are no errors. + */ + protected function readProcessErrors(): string + { + return (string) stream_get_contents($this->pipes[2]); + } + + /** + * Writes to the input stream of the opened process. + * + * @codeCoverageIgnore + */ + protected function writeProcessInput(string $string): void + { + fwrite($this->pipes[0], $string); + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + if (is_resource($this->process)) { + foreach ($this->pipes as $pipe) { + fclose($pipe); + } + proc_close($this->process); + $this->process = null; + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php new file mode 100644 index 0000000..3adec7a --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.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 Monolog\Handler; + +use Monolog\Processor\ProcessorInterface; + +/** + * Interface to describe loggers that have processors + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + */ +interface ProcessableHandlerInterface +{ + /** + * Adds a processor in the stack. + * + * @psalm-param ProcessorInterface|callable(Record): Record $callback + * + * @param ProcessorInterface|callable $callback + * @return HandlerInterface self + */ + public function pushProcessor(callable $callback): HandlerInterface; + + /** + * Removes the processor on top of the stack and returns it. + * + * @psalm-return ProcessorInterface|callable(Record): Record $callback + * + * @throws \LogicException In case the processor stack is empty + * @return callable|ProcessorInterface + */ + public function popProcessor(): callable; +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php new file mode 100644 index 0000000..9ef6e30 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.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 Monolog\Handler; + +use Monolog\ResettableInterface; +use Monolog\Processor\ProcessorInterface; + +/** + * Helper trait for implementing ProcessableInterface + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + */ +trait ProcessableHandlerTrait +{ + /** + * @var callable[] + * @phpstan-var array + */ + protected $processors = []; + + /** + * {@inheritDoc} + */ + public function pushProcessor(callable $callback): HandlerInterface + { + array_unshift($this->processors, $callback); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function popProcessor(): callable + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * Processes a record. + * + * @phpstan-param Record $record + * @phpstan-return Record + */ + protected function processRecord(array $record): array + { + foreach ($this->processors as $processor) { + $record = $processor($record); + } + + return $record; + } + + protected function resetProcessors(): void + { + foreach ($this->processors as $processor) { + if ($processor instanceof ResettableInterface) { + $processor->reset(); + } + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php new file mode 100644 index 0000000..36e19cc --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Psr\Log\LoggerInterface; +use Monolog\Formatter\FormatterInterface; + +/** + * Proxies log messages to an existing PSR-3 compliant logger. + * + * If a formatter is configured, the formatter's output MUST be a string and the + * formatted message will be fed to the wrapped PSR logger instead of the original + * log record's message. + * + * @author Michael Moussa + */ +class PsrHandler extends AbstractHandler implements FormattableHandlerInterface +{ + /** + * PSR-3 compliant logger + * + * @var LoggerInterface + */ + protected $logger; + + /** + * @var FormatterInterface|null + */ + protected $formatter; + + /** + * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied + */ + public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true) + { + parent::__construct($level, $bubble); + + $this->logger = $logger; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if (!$this->isHandling($record)) { + return false; + } + + if ($this->formatter) { + $formatted = $this->formatter->format($record); + $this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']); + } else { + $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); + } + + return false === $this->bubble; + } + + /** + * Sets the formatter. + * + * @param FormatterInterface $formatter + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + $this->formatter = $formatter; + + return $this; + } + + /** + * Gets the formatter. + * + * @return FormatterInterface + */ + public function getFormatter(): FormatterInterface + { + if (!$this->formatter) { + throw new \LogicException('No formatter has been set and this handler does not have a default formatter'); + } + + return $this->formatter; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php new file mode 100644 index 0000000..fed2303 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -0,0 +1,246 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; +use Psr\Log\LogLevel; + +/** + * Sends notifications through the pushover api to mobile phones + * + * @author Sebastian Göttschkes + * @see https://www.pushover.net/api + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class PushoverHandler extends SocketHandler +{ + /** @var string */ + private $token; + /** @var array */ + private $users; + /** @var string */ + private $title; + /** @var string|int|null */ + private $user = null; + /** @var int */ + private $retry; + /** @var int */ + private $expire; + + /** @var int */ + private $highPriorityLevel; + /** @var int */ + private $emergencyLevel; + /** @var bool */ + private $useFormattedMessage = false; + + /** + * All parameters that can be sent to Pushover + * @see https://pushover.net/api + * @var array + */ + private $parameterNames = [ + 'token' => true, + 'user' => true, + 'message' => true, + 'device' => true, + 'title' => true, + 'url' => true, + 'url_title' => true, + 'priority' => true, + 'timestamp' => true, + 'sound' => true, + 'retry' => true, + 'expire' => true, + 'callback' => true, + ]; + + /** + * Sounds the api supports by default + * @see https://pushover.net/api#sounds + * @var string[] + */ + private $sounds = [ + 'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', + 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', + 'persistent', 'echo', 'updown', 'none', + ]; + + /** + * @param string $token Pushover api token + * @param string|array $users Pushover user id or array of ids the message will be sent to + * @param string|null $title Title sent to the Pushover API + * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not + * the pushover.net app owner. OpenSSL is required for this option. + * @param string|int $highPriorityLevel The minimum logging level at which this handler will start + * sending "high priority" requests to the Pushover API + * @param string|int $emergencyLevel The minimum logging level at which this handler will start + * sending "emergency" requests to the Pushover API + * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will + * send the same notification to the user. + * @param int $expire The expire parameter specifies how many seconds your notification will continue + * to be retried for (every retry seconds). + * + * @phpstan-param string|array $users + * @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel + * @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel + */ + public function __construct( + string $token, + $users, + ?string $title = null, + $level = Logger::CRITICAL, + bool $bubble = true, + bool $useSSL = true, + $highPriorityLevel = Logger::CRITICAL, + $emergencyLevel = Logger::EMERGENCY, + int $retry = 30, + int $expire = 25200, + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80'; + parent::__construct( + $connectionString, + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + + $this->token = $token; + $this->users = (array) $users; + $this->title = $title ?: (string) gethostname(); + $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel); + $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel); + $this->retry = $retry; + $this->expire = $expire; + } + + protected function generateDataStream(array $record): string + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * @phpstan-param FormattedRecord $record + */ + private function buildContent(array $record): string + { + // Pushover has a limit of 512 characters on title and message combined. + $maxMessageLength = 512 - strlen($this->title); + + $message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message']; + $message = Utils::substr($message, 0, $maxMessageLength); + + $timestamp = $record['datetime']->getTimestamp(); + + $dataArray = [ + 'token' => $this->token, + 'user' => $this->user, + 'message' => $message, + 'title' => $this->title, + 'timestamp' => $timestamp, + ]; + + if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) { + $dataArray['priority'] = 2; + $dataArray['retry'] = $this->retry; + $dataArray['expire'] = $this->expire; + } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) { + $dataArray['priority'] = 1; + } + + // First determine the available parameters + $context = array_intersect_key($record['context'], $this->parameterNames); + $extra = array_intersect_key($record['extra'], $this->parameterNames); + + // Least important info should be merged with subsequent info + $dataArray = array_merge($extra, $context, $dataArray); + + // Only pass sounds that are supported by the API + if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) { + unset($dataArray['sound']); + } + + return http_build_query($dataArray); + } + + private function buildHeader(string $content): string + { + $header = "POST /1/messages.json HTTP/1.1\r\n"; + $header .= "Host: api.pushover.net\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + protected function write(array $record): void + { + foreach ($this->users as $user) { + $this->user = $user; + + parent::write($record); + $this->closeSocket(); + } + + $this->user = null; + } + + /** + * @param int|string $value + * + * @phpstan-param Level|LevelName|LogLevel::* $value + */ + public function setHighPriorityLevel($value): self + { + $this->highPriorityLevel = Logger::toMonologLevel($value); + + return $this; + } + + /** + * @param int|string $value + * + * @phpstan-param Level|LevelName|LogLevel::* $value + */ + public function setEmergencyLevel($value): self + { + $this->emergencyLevel = Logger::toMonologLevel($value); + + return $this; + } + + /** + * Use the formatted message? + */ + public function useFormattedMessage(bool $value): self + { + $this->useFormattedMessage = $value; + + return $this; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php new file mode 100644 index 0000000..91d16ea --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.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 Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; + +/** + * Logs to a Redis key using rpush + * + * usage example: + * + * $log = new Logger('application'); + * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); + * $log->pushHandler($redis); + * + * @author Thomas Tourlourat + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class RedisHandler extends AbstractProcessingHandler +{ + /** @var \Predis\Client<\Predis\Client>|\Redis */ + private $redisClient; + /** @var string */ + private $redisKey; + /** @var int */ + protected $capSize; + + /** + * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance + * @param string $key The key name to push records to + * @param int $capSize Number of entries to limit list size to, 0 = unlimited + */ + public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0) + { + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); + } + + $this->redisClient = $redis; + $this->redisKey = $key; + $this->capSize = $capSize; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if ($this->capSize) { + $this->writeCapped($record); + } else { + $this->redisClient->rpush($this->redisKey, $record["formatted"]); + } + } + + /** + * Write and cap the collection + * Writes the record to the redis list and caps its + * + * @phpstan-param FormattedRecord $record + */ + protected function writeCapped(array $record): void + { + if ($this->redisClient instanceof \Redis) { + $mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1; + $this->redisClient->multi($mode) + ->rpush($this->redisKey, $record["formatted"]) + ->ltrim($this->redisKey, -$this->capSize, -1) + ->exec(); + } else { + $redisKey = $this->redisKey; + $capSize = $this->capSize; + $this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) { + $tx->rpush($redisKey, $record["formatted"]); + $tx->ltrim($redisKey, -$capSize, -1); + }); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php new file mode 100644 index 0000000..7789309 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.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 Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; + +/** + * Sends the message to a Redis Pub/Sub channel using PUBLISH + * + * usage example: + * + * $log = new Logger('application'); + * $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING); + * $log->pushHandler($redis); + * + * @author Gaëtan Faugère + */ +class RedisPubSubHandler extends AbstractProcessingHandler +{ + /** @var \Predis\Client<\Predis\Client>|\Redis */ + private $redisClient; + /** @var string */ + private $channelKey; + + /** + * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance + * @param string $key The channel key to publish records to + */ + public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true) + { + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); + } + + $this->redisClient = $redis; + $this->channelKey = $key; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->redisClient->publish($this->channelKey, $record["formatted"]); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter(): FormatterInterface + { + return new LineFormatter(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php new file mode 100644 index 0000000..adcc939 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.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 Monolog\Handler; + +use Rollbar\RollbarLogger; +use Throwable; +use Monolog\Logger; + +/** + * Sends errors to Rollbar + * + * If the context data contains a `payload` key, that is used as an array + * of payload options to RollbarLogger's log method. + * + * Rollbar's context info will contain the context + extra keys from the log record + * merged, and then on top of that a few keys: + * + * - level (rollbar level name) + * - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8) + * - channel + * - datetime (unix timestamp) + * + * @author Paul Statezny + */ +class RollbarHandler extends AbstractProcessingHandler +{ + /** + * @var RollbarLogger + */ + protected $rollbarLogger; + + /** @var string[] */ + protected $levelMap = [ + Logger::DEBUG => 'debug', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warning', + Logger::ERROR => 'error', + Logger::CRITICAL => 'critical', + Logger::ALERT => 'critical', + Logger::EMERGENCY => 'critical', + ]; + + /** + * Records whether any log records have been added since the last flush of the rollbar notifier + * + * @var bool + */ + private $hasRecords = false; + + /** @var bool */ + protected $initialized = false; + + /** + * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token + */ + public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true) + { + $this->rollbarLogger = $rollbarLogger; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if (!$this->initialized) { + // __destructor() doesn't get called on Fatal errors + register_shutdown_function(array($this, 'close')); + $this->initialized = true; + } + + $context = $record['context']; + $context = array_merge($context, $record['extra'], [ + 'level' => $this->levelMap[$record['level']], + 'monolog_level' => $record['level_name'], + 'channel' => $record['channel'], + 'datetime' => $record['datetime']->format('U'), + ]); + + if (isset($context['exception']) && $context['exception'] instanceof Throwable) { + $exception = $context['exception']; + unset($context['exception']); + $toLog = $exception; + } else { + $toLog = $record['message']; + } + + // @phpstan-ignore-next-line + $this->rollbarLogger->log($context['level'], $toLog, $context); + + $this->hasRecords = true; + } + + public function flush(): void + { + if ($this->hasRecords) { + $this->rollbarLogger->flush(); + $this->hasRecords = false; + } + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + $this->flush(); + } + + /** + * {@inheritDoc} + */ + public function reset() + { + $this->flush(); + + parent::reset(); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php new file mode 100644 index 0000000..17745d2 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -0,0 +1,207 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use InvalidArgumentException; +use Monolog\Logger; +use Monolog\Utils; + +/** + * Stores logs to files that are rotated every day and a limited number of files are kept. + * + * This rotation is only intended to be used as a workaround. Using logrotate to + * handle the rotation is strongly encouraged when you can use it. + * + * @author Christophe Coevoet + * @author Jordi Boggiano + */ +class RotatingFileHandler extends StreamHandler +{ + public const FILE_PER_DAY = 'Y-m-d'; + public const FILE_PER_MONTH = 'Y-m'; + public const FILE_PER_YEAR = 'Y'; + + /** @var string */ + protected $filename; + /** @var int */ + protected $maxFiles; + /** @var bool */ + protected $mustRotate; + /** @var \DateTimeImmutable */ + protected $nextRotation; + /** @var string */ + protected $filenameFormat; + /** @var string */ + protected $dateFormat; + + /** + * @param string $filename + * @param int $maxFiles The maximal amount of files to keep (0 means unlimited) + * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param bool $useLocking Try to lock log file before doing any writes + */ + public function __construct(string $filename, int $maxFiles = 0, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) + { + $this->filename = Utils::canonicalizePath($filename); + $this->maxFiles = $maxFiles; + $this->nextRotation = new \DateTimeImmutable('tomorrow'); + $this->filenameFormat = '{filename}-{date}'; + $this->dateFormat = static::FILE_PER_DAY; + + parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + parent::close(); + + if (true === $this->mustRotate) { + $this->rotate(); + } + } + + /** + * {@inheritDoc} + */ + public function reset() + { + parent::reset(); + + if (true === $this->mustRotate) { + $this->rotate(); + } + } + + public function setFilenameFormat(string $filenameFormat, string $dateFormat): self + { + if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) { + throw new InvalidArgumentException( + 'Invalid date format - format must be one of '. + 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '. + 'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '. + 'date formats using slashes, underscores and/or dots instead of dashes.' + ); + } + if (substr_count($filenameFormat, '{date}') === 0) { + throw new InvalidArgumentException( + 'Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.' + ); + } + $this->filenameFormat = $filenameFormat; + $this->dateFormat = $dateFormat; + $this->url = $this->getTimedFilename(); + $this->close(); + + return $this; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + // on the first record written, if the log is new, we should rotate (once per day) + if (null === $this->mustRotate) { + $this->mustRotate = null === $this->url || !file_exists($this->url); + } + + if ($this->nextRotation <= $record['datetime']) { + $this->mustRotate = true; + $this->close(); + } + + parent::write($record); + } + + /** + * Rotates the files. + */ + protected function rotate(): void + { + // update filename + $this->url = $this->getTimedFilename(); + $this->nextRotation = new \DateTimeImmutable('tomorrow'); + + // skip GC of old logs if files are unlimited + if (0 === $this->maxFiles) { + return; + } + + $logFiles = glob($this->getGlobPattern()); + if (false === $logFiles) { + // failed to glob + return; + } + + if ($this->maxFiles >= count($logFiles)) { + // no files to remove + return; + } + + // Sorting the files by name to remove the older ones + usort($logFiles, function ($a, $b) { + return strcmp($b, $a); + }); + + foreach (array_slice($logFiles, $this->maxFiles) as $file) { + if (is_writable($file)) { + // suppress errors here as unlink() might fail if two processes + // are cleaning up/rotating at the same time + set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool { + return false; + }); + unlink($file); + restore_error_handler(); + } + } + + $this->mustRotate = false; + } + + protected function getTimedFilename(): string + { + $fileInfo = pathinfo($this->filename); + $timedFilename = str_replace( + ['{filename}', '{date}'], + [$fileInfo['filename'], date($this->dateFormat)], + $fileInfo['dirname'] . '/' . $this->filenameFormat + ); + + if (isset($fileInfo['extension'])) { + $timedFilename .= '.'.$fileInfo['extension']; + } + + return $timedFilename; + } + + protected function getGlobPattern(): string + { + $fileInfo = pathinfo($this->filename); + $glob = str_replace( + ['{filename}', '{date}'], + [$fileInfo['filename'], str_replace( + ['Y', 'y', 'm', 'd'], + ['[0-9][0-9][0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]'], + $this->dateFormat) + ], + $fileInfo['dirname'] . '/' . $this->filenameFormat + ); + if (isset($fileInfo['extension'])) { + $glob .= '.'.$fileInfo['extension']; + } + + return $glob; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php new file mode 100644 index 0000000..c128a32 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; + +/** + * Sampling handler + * + * A sampled event stream can be useful for logging high frequency events in + * a production environment where you only need an idea of what is happening + * and are not concerned with capturing every occurrence. Since the decision to + * handle or not handle a particular event is determined randomly, the + * resulting sampled log is not guaranteed to contain 1/N of the events that + * occurred in the application, but based on the Law of large numbers, it will + * tend to be close to this ratio with a large number of attempts. + * + * @author Bryan Davis + * @author Kunal Mehta + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + */ +class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface +{ + use ProcessableHandlerTrait; + + /** + * @var HandlerInterface|callable + * @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface + */ + protected $handler; + + /** + * @var int $factor + */ + protected $factor; + + /** + * @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler + * + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler). + * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled) + */ + public function __construct($handler, int $factor) + { + parent::__construct(); + $this->handler = $handler; + $this->factor = $factor; + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } + } + + public function isHandling(array $record): bool + { + return $this->getHandler($record)->isHandling($record); + } + + public function handle(array $record): bool + { + if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + $this->getHandler($record)->handle($record); + } + + return false === $this->bubble; + } + + /** + * Return the nested handler + * + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @phpstan-param Record|array{level: Level}|null $record + * + * @return HandlerInterface + */ + public function getHandler(array $record = null) + { + if (!$this->handler instanceof HandlerInterface) { + $this->handler = ($this->handler)($record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + return $this->handler; + } + + /** + * {@inheritDoc} + */ + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + $handler = $this->getHandler(); + if ($handler instanceof FormattableHandlerInterface) { + $handler->setFormatter($formatter); + + return $this; + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); + } + + /** + * {@inheritDoc} + */ + public function getFormatter(): FormatterInterface + { + $handler = $this->getHandler(); + if ($handler instanceof FormattableHandlerInterface) { + return $handler->getFormatter(); + } + + throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php new file mode 100644 index 0000000..1280ee7 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.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 Monolog\Handler; + +use Monolog\Logger; + +/** + * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html + * + * @author Ricardo Fontanelli + */ +class SendGridHandler extends MailHandler +{ + /** + * The SendGrid API User + * @var string + */ + protected $apiUser; + + /** + * The SendGrid API Key + * @var string + */ + protected $apiKey; + + /** + * The email addresses to which the message will be sent + * @var string + */ + protected $from; + + /** + * The email addresses to which the message will be sent + * @var string[] + */ + protected $to; + + /** + * The subject of the email + * @var string + */ + protected $subject; + + /** + * @param string $apiUser The SendGrid API User + * @param string $apiKey The SendGrid API Key + * @param string $from The sender of the email + * @param string|string[] $to The recipients of the email + * @param string $subject The subject of the mail + */ + public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true) + { + if (!extension_loaded('curl')) { + throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler'); + } + + parent::__construct($level, $bubble); + $this->apiUser = $apiUser; + $this->apiKey = $apiKey; + $this->from = $from; + $this->to = (array) $to; + $this->subject = $subject; + } + + /** + * {@inheritDoc} + */ + protected function send(string $content, array $records): void + { + $message = []; + $message['api_user'] = $this->apiUser; + $message['api_key'] = $this->apiKey; + $message['from'] = $this->from; + foreach ($this->to as $recipient) { + $message['to[]'] = $recipient; + } + $message['subject'] = $this->subject; + $message['date'] = date('r'); + + if ($this->isHtmlBody($content)) { + $message['html'] = $content; + } else { + $message['text'] = $content; + } + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json'); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message)); + Curl\Util::execute($ch, 2); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php new file mode 100644 index 0000000..71a4109 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php @@ -0,0 +1,387 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler\Slack; + +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Formatter\NormalizerFormatter; +use Monolog\Formatter\FormatterInterface; + +/** + * Slack record utility helping to log to Slack webhooks or API. + * + * @author Greg Kedzierski + * @author Haralan Dobrev + * @see https://api.slack.com/incoming-webhooks + * @see https://api.slack.com/docs/message-attachments + * + * @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler + * @phpstan-import-type Record from \Monolog\Logger + */ +class SlackRecord +{ + public const COLOR_DANGER = 'danger'; + + public const COLOR_WARNING = 'warning'; + + public const COLOR_GOOD = 'good'; + + public const COLOR_DEFAULT = '#e3e4e6'; + + /** + * Slack channel (encoded ID or name) + * @var string|null + */ + private $channel; + + /** + * Name of a bot + * @var string|null + */ + private $username; + + /** + * User icon e.g. 'ghost', 'http://example.com/user.png' + * @var string|null + */ + private $userIcon; + + /** + * Whether the message should be added to Slack as attachment (plain text otherwise) + * @var bool + */ + private $useAttachment; + + /** + * Whether the the context/extra messages added to Slack as attachments are in a short style + * @var bool + */ + private $useShortAttachment; + + /** + * Whether the attachment should include context and extra data + * @var bool + */ + private $includeContextAndExtra; + + /** + * Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] + * @var string[] + */ + private $excludeFields; + + /** + * @var ?FormatterInterface + */ + private $formatter; + + /** + * @var NormalizerFormatter + */ + private $normalizerFormatter; + + /** + * @param string[] $excludeFields + */ + public function __construct( + ?string $channel = null, + ?string $username = null, + bool $useAttachment = true, + ?string $userIcon = null, + bool $useShortAttachment = false, + bool $includeContextAndExtra = false, + array $excludeFields = array(), + FormatterInterface $formatter = null + ) { + $this + ->setChannel($channel) + ->setUsername($username) + ->useAttachment($useAttachment) + ->setUserIcon($userIcon) + ->useShortAttachment($useShortAttachment) + ->includeContextAndExtra($includeContextAndExtra) + ->excludeFields($excludeFields) + ->setFormatter($formatter); + + if ($this->includeContextAndExtra) { + $this->normalizerFormatter = new NormalizerFormatter(); + } + } + + /** + * Returns required data in format that Slack + * is expecting. + * + * @phpstan-param FormattedRecord $record + * @phpstan-return mixed[] + */ + public function getSlackData(array $record): array + { + $dataArray = array(); + $record = $this->removeExcludedFields($record); + + if ($this->username) { + $dataArray['username'] = $this->username; + } + + if ($this->channel) { + $dataArray['channel'] = $this->channel; + } + + if ($this->formatter && !$this->useAttachment) { + /** @phpstan-ignore-next-line */ + $message = $this->formatter->format($record); + } else { + $message = $record['message']; + } + + if ($this->useAttachment) { + $attachment = array( + 'fallback' => $message, + 'text' => $message, + 'color' => $this->getAttachmentColor($record['level']), + 'fields' => array(), + 'mrkdwn_in' => array('fields'), + 'ts' => $record['datetime']->getTimestamp(), + 'footer' => $this->username, + 'footer_icon' => $this->userIcon, + ); + + if ($this->useShortAttachment) { + $attachment['title'] = $record['level_name']; + } else { + $attachment['title'] = 'Message'; + $attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']); + } + + if ($this->includeContextAndExtra) { + foreach (array('extra', 'context') as $key) { + if (empty($record[$key])) { + continue; + } + + if ($this->useShortAttachment) { + $attachment['fields'][] = $this->generateAttachmentField( + (string) $key, + $record[$key] + ); + } else { + // Add all extra fields as individual fields in attachment + $attachment['fields'] = array_merge( + $attachment['fields'], + $this->generateAttachmentFields($record[$key]) + ); + } + } + } + + $dataArray['attachments'] = array($attachment); + } else { + $dataArray['text'] = $message; + } + + if ($this->userIcon) { + if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) { + $dataArray['icon_url'] = $this->userIcon; + } else { + $dataArray['icon_emoji'] = ":{$this->userIcon}:"; + } + } + + return $dataArray; + } + + /** + * Returns a Slack message attachment color associated with + * provided level. + */ + public function getAttachmentColor(int $level): string + { + switch (true) { + case $level >= Logger::ERROR: + return static::COLOR_DANGER; + case $level >= Logger::WARNING: + return static::COLOR_WARNING; + case $level >= Logger::INFO: + return static::COLOR_GOOD; + default: + return static::COLOR_DEFAULT; + } + } + + /** + * Stringifies an array of key/value pairs to be used in attachment fields + * + * @param mixed[] $fields + */ + public function stringify(array $fields): string + { + /** @var Record $fields */ + $normalized = $this->normalizerFormatter->format($fields); + + $hasSecondDimension = count(array_filter($normalized, 'is_array')); + $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric')); + + return $hasSecondDimension || $hasNonNumericKeys + ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT|Utils::DEFAULT_JSON_FLAGS) + : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS); + } + + /** + * Channel used by the bot when posting + * + * @param ?string $channel + * + * @return static + */ + public function setChannel(?string $channel = null): self + { + $this->channel = $channel; + + return $this; + } + + /** + * Username used by the bot when posting + * + * @param ?string $username + * + * @return static + */ + public function setUsername(?string $username = null): self + { + $this->username = $username; + + return $this; + } + + public function useAttachment(bool $useAttachment = true): self + { + $this->useAttachment = $useAttachment; + + return $this; + } + + public function setUserIcon(?string $userIcon = null): self + { + $this->userIcon = $userIcon; + + if (\is_string($userIcon)) { + $this->userIcon = trim($userIcon, ':'); + } + + return $this; + } + + public function useShortAttachment(bool $useShortAttachment = false): self + { + $this->useShortAttachment = $useShortAttachment; + + return $this; + } + + public function includeContextAndExtra(bool $includeContextAndExtra = false): self + { + $this->includeContextAndExtra = $includeContextAndExtra; + + if ($this->includeContextAndExtra) { + $this->normalizerFormatter = new NormalizerFormatter(); + } + + return $this; + } + + /** + * @param string[] $excludeFields + */ + public function excludeFields(array $excludeFields = []): self + { + $this->excludeFields = $excludeFields; + + return $this; + } + + public function setFormatter(?FormatterInterface $formatter = null): self + { + $this->formatter = $formatter; + + return $this; + } + + /** + * Generates attachment field + * + * @param string|mixed[] $value + * + * @return array{title: string, value: string, short: false} + */ + private function generateAttachmentField(string $title, $value): array + { + $value = is_array($value) + ? sprintf('```%s```', substr($this->stringify($value), 0, 1990)) + : $value; + + return array( + 'title' => ucfirst($title), + 'value' => $value, + 'short' => false, + ); + } + + /** + * Generates a collection of attachment fields from array + * + * @param mixed[] $data + * + * @return array + */ + private function generateAttachmentFields(array $data): array + { + /** @var Record $data */ + $normalized = $this->normalizerFormatter->format($data); + + $fields = array(); + foreach ($normalized as $key => $value) { + $fields[] = $this->generateAttachmentField((string) $key, $value); + } + + return $fields; + } + + /** + * Get a copy of record with fields excluded according to $this->excludeFields + * + * @phpstan-param FormattedRecord $record + * + * @return mixed[] + */ + private function removeExcludedFields(array $record): array + { + foreach ($this->excludeFields as $field) { + $keys = explode('.', $field); + $node = &$record; + $lastKey = end($keys); + foreach ($keys as $key) { + if (!isset($node[$key])) { + break; + } + if ($lastKey === $key) { + unset($node[$key]); + break; + } + $node = &$node[$key]; + } + } + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php new file mode 100644 index 0000000..a648513 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php @@ -0,0 +1,256 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Handler\Slack\SlackRecord; + +/** + * Sends notifications through Slack API + * + * @author Greg Kedzierski + * @see https://api.slack.com/ + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class SlackHandler extends SocketHandler +{ + /** + * Slack API token + * @var string + */ + private $token; + + /** + * Instance of the SlackRecord util class preparing data for Slack API. + * @var SlackRecord + */ + private $slackRecord; + + /** + * @param string $token Slack API token + * @param string $channel Slack channel (encoded ID or name) + * @param string|null $username Name of a bot + * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) + * @param string|null $iconEmoji The emoji name to use (or null) + * @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style + * @param bool $includeContextAndExtra Whether the attachment should include context and extra data + * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] + * @throws MissingExtensionException If no OpenSSL PHP extension configured + */ + public function __construct( + string $token, + string $channel, + ?string $username = null, + bool $useAttachment = true, + ?string $iconEmoji = null, + $level = Logger::CRITICAL, + bool $bubble = true, + bool $useShortAttachment = false, + bool $includeContextAndExtra = false, + array $excludeFields = array(), + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler'); + } + + parent::__construct( + 'ssl://slack.com:443', + $level, + $bubble, + $persistent, + $timeout, + $writingTimeout, + $connectionTimeout, + $chunkSize + ); + + $this->slackRecord = new SlackRecord( + $channel, + $username, + $useAttachment, + $iconEmoji, + $useShortAttachment, + $includeContextAndExtra, + $excludeFields + ); + + $this->token = $token; + } + + public function getSlackRecord(): SlackRecord + { + return $this->slackRecord; + } + + public function getToken(): string + { + return $this->token; + } + + /** + * {@inheritDoc} + */ + protected function generateDataStream(array $record): string + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @phpstan-param FormattedRecord $record + */ + private function buildContent(array $record): string + { + $dataArray = $this->prepareContentData($record); + + return http_build_query($dataArray); + } + + /** + * @phpstan-param FormattedRecord $record + * @return string[] + */ + protected function prepareContentData(array $record): array + { + $dataArray = $this->slackRecord->getSlackData($record); + $dataArray['token'] = $this->token; + + if (!empty($dataArray['attachments'])) { + $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']); + } + + return $dataArray; + } + + /** + * Builds the header of the API Call + */ + private function buildHeader(string $content): string + { + $header = "POST /api/chat.postMessage HTTP/1.1\r\n"; + $header .= "Host: slack.com\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + parent::write($record); + $this->finalizeWrite(); + } + + /** + * Finalizes the request by reading some bytes and then closing the socket + * + * If we do not read some but close the socket too early, slack sometimes + * drops the request entirely. + */ + protected function finalizeWrite(): void + { + $res = $this->getResource(); + if (is_resource($res)) { + @fread($res, 2048); + } + $this->closeSocket(); + } + + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + parent::setFormatter($formatter); + $this->slackRecord->setFormatter($formatter); + + return $this; + } + + public function getFormatter(): FormatterInterface + { + $formatter = parent::getFormatter(); + $this->slackRecord->setFormatter($formatter); + + return $formatter; + } + + /** + * Channel used by the bot when posting + */ + public function setChannel(string $channel): self + { + $this->slackRecord->setChannel($channel); + + return $this; + } + + /** + * Username used by the bot when posting + */ + public function setUsername(string $username): self + { + $this->slackRecord->setUsername($username); + + return $this; + } + + public function useAttachment(bool $useAttachment): self + { + $this->slackRecord->useAttachment($useAttachment); + + return $this; + } + + public function setIconEmoji(string $iconEmoji): self + { + $this->slackRecord->setUserIcon($iconEmoji); + + return $this; + } + + public function useShortAttachment(bool $useShortAttachment): self + { + $this->slackRecord->useShortAttachment($useShortAttachment); + + return $this; + } + + public function includeContextAndExtra(bool $includeContextAndExtra): self + { + $this->slackRecord->includeContextAndExtra($includeContextAndExtra); + + return $this; + } + + /** + * @param string[] $excludeFields + */ + public function excludeFields(array $excludeFields): self + { + $this->slackRecord->excludeFields($excludeFields); + + return $this; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php new file mode 100644 index 0000000..8ae3c78 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Handler\Slack\SlackRecord; + +/** + * Sends notifications through Slack Webhooks + * + * @author Haralan Dobrev + * @see https://api.slack.com/incoming-webhooks + */ +class SlackWebhookHandler extends AbstractProcessingHandler +{ + /** + * Slack Webhook token + * @var string + */ + private $webhookUrl; + + /** + * Instance of the SlackRecord util class preparing data for Slack API. + * @var SlackRecord + */ + private $slackRecord; + + /** + * @param string $webhookUrl Slack Webhook URL + * @param string|null $channel Slack channel (encoded ID or name) + * @param string|null $username Name of a bot + * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) + * @param string|null $iconEmoji The emoji name to use (or null) + * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style + * @param bool $includeContextAndExtra Whether the attachment should include context and extra data + * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] + */ + public function __construct( + string $webhookUrl, + ?string $channel = null, + ?string $username = null, + bool $useAttachment = true, + ?string $iconEmoji = null, + bool $useShortAttachment = false, + bool $includeContextAndExtra = false, + $level = Logger::CRITICAL, + bool $bubble = true, + array $excludeFields = array() + ) { + if (!extension_loaded('curl')) { + throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler'); + } + + parent::__construct($level, $bubble); + + $this->webhookUrl = $webhookUrl; + + $this->slackRecord = new SlackRecord( + $channel, + $username, + $useAttachment, + $iconEmoji, + $useShortAttachment, + $includeContextAndExtra, + $excludeFields + ); + } + + public function getSlackRecord(): SlackRecord + { + return $this->slackRecord; + } + + public function getWebhookUrl(): string + { + return $this->webhookUrl; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $postData = $this->slackRecord->getSlackData($record); + $postString = Utils::jsonEncode($postData); + + $ch = curl_init(); + $options = array( + CURLOPT_URL => $this->webhookUrl, + CURLOPT_POST => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => array('Content-type: application/json'), + CURLOPT_POSTFIELDS => $postString, + ); + if (defined('CURLOPT_SAFE_UPLOAD')) { + $options[CURLOPT_SAFE_UPLOAD] = true; + } + + curl_setopt_array($ch, $options); + + Curl\Util::execute($ch); + } + + public function setFormatter(FormatterInterface $formatter): HandlerInterface + { + parent::setFormatter($formatter); + $this->slackRecord->setFormatter($formatter); + + return $this; + } + + public function getFormatter(): FormatterInterface + { + $formatter = parent::getFormatter(); + $this->slackRecord->setFormatter($formatter); + + return $formatter; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php new file mode 100644 index 0000000..21701af --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php @@ -0,0 +1,448 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Stores to any socket - uses fsockopen() or pfsockopen(). + * + * @author Pablo de Leon Belloc + * @see http://php.net/manual/en/function.fsockopen.php + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class SocketHandler extends AbstractProcessingHandler +{ + /** @var string */ + private $connectionString; + /** @var float */ + private $connectionTimeout; + /** @var resource|null */ + private $resource; + /** @var float */ + private $timeout; + /** @var float */ + private $writingTimeout; + /** @var ?int */ + private $lastSentBytes = null; + /** @var ?int */ + private $chunkSize; + /** @var bool */ + private $persistent; + /** @var ?int */ + private $errno = null; + /** @var ?string */ + private $errstr = null; + /** @var ?float */ + private $lastWritingAt = null; + + /** + * @param string $connectionString Socket connection string + * @param bool $persistent Flag to enable/disable persistent connections + * @param float $timeout Socket timeout to wait until the request is being aborted + * @param float $writingTimeout Socket timeout to wait until the request should've been sent/written + * @param float|null $connectionTimeout Socket connect timeout to wait until the connection should've been + * established + * @param int|null $chunkSize Sets the chunk size. Only has effect during connection in the writing cycle + * + * @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed. + */ + public function __construct( + string $connectionString, + $level = Logger::DEBUG, + bool $bubble = true, + bool $persistent = false, + float $timeout = 0.0, + float $writingTimeout = 10.0, + ?float $connectionTimeout = null, + ?int $chunkSize = null + ) { + parent::__construct($level, $bubble); + $this->connectionString = $connectionString; + + if ($connectionTimeout !== null) { + $this->validateTimeout($connectionTimeout); + } + + $this->connectionTimeout = $connectionTimeout ?? (float) ini_get('default_socket_timeout'); + $this->persistent = $persistent; + $this->validateTimeout($timeout); + $this->timeout = $timeout; + $this->validateTimeout($writingTimeout); + $this->writingTimeout = $writingTimeout; + $this->chunkSize = $chunkSize; + } + + /** + * Connect (if necessary) and write to the socket + * + * {@inheritDoc} + * + * @throws \UnexpectedValueException + * @throws \RuntimeException + */ + protected function write(array $record): void + { + $this->connectIfNotConnected(); + $data = $this->generateDataStream($record); + $this->writeToSocket($data); + } + + /** + * We will not close a PersistentSocket instance so it can be reused in other requests. + */ + public function close(): void + { + if (!$this->isPersistent()) { + $this->closeSocket(); + } + } + + /** + * Close socket, if open + */ + public function closeSocket(): void + { + if (is_resource($this->resource)) { + fclose($this->resource); + $this->resource = null; + } + } + + /** + * Set socket connection to be persistent. It only has effect before the connection is initiated. + */ + public function setPersistent(bool $persistent): self + { + $this->persistent = $persistent; + + return $this; + } + + /** + * Set connection timeout. Only has effect before we connect. + * + * @see http://php.net/manual/en/function.fsockopen.php + */ + public function setConnectionTimeout(float $seconds): self + { + $this->validateTimeout($seconds); + $this->connectionTimeout = $seconds; + + return $this; + } + + /** + * Set write timeout. Only has effect before we connect. + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + */ + public function setTimeout(float $seconds): self + { + $this->validateTimeout($seconds); + $this->timeout = $seconds; + + return $this; + } + + /** + * Set writing timeout. Only has effect during connection in the writing cycle. + * + * @param float $seconds 0 for no timeout + */ + public function setWritingTimeout(float $seconds): self + { + $this->validateTimeout($seconds); + $this->writingTimeout = $seconds; + + return $this; + } + + /** + * Set chunk size. Only has effect during connection in the writing cycle. + */ + public function setChunkSize(int $bytes): self + { + $this->chunkSize = $bytes; + + return $this; + } + + /** + * Get current connection string + */ + public function getConnectionString(): string + { + return $this->connectionString; + } + + /** + * Get persistent setting + */ + public function isPersistent(): bool + { + return $this->persistent; + } + + /** + * Get current connection timeout setting + */ + public function getConnectionTimeout(): float + { + return $this->connectionTimeout; + } + + /** + * Get current in-transfer timeout + */ + public function getTimeout(): float + { + return $this->timeout; + } + + /** + * Get current local writing timeout + * + * @return float + */ + public function getWritingTimeout(): float + { + return $this->writingTimeout; + } + + /** + * Get current chunk size + */ + public function getChunkSize(): ?int + { + return $this->chunkSize; + } + + /** + * Check to see if the socket is currently available. + * + * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. + */ + public function isConnected(): bool + { + return is_resource($this->resource) + && !feof($this->resource); // on TCP - other party can close connection. + } + + /** + * Wrapper to allow mocking + * + * @return resource|false + */ + protected function pfsockopen() + { + return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Wrapper to allow mocking + * + * @return resource|false + */ + protected function fsockopen() + { + return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Wrapper to allow mocking + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + * + * @return bool + */ + protected function streamSetTimeout() + { + $seconds = floor($this->timeout); + $microseconds = round(($this->timeout - $seconds) * 1e6); + + if (!is_resource($this->resource)) { + throw new \LogicException('streamSetTimeout called but $this->resource is not a resource'); + } + + return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds); + } + + /** + * Wrapper to allow mocking + * + * @see http://php.net/manual/en/function.stream-set-chunk-size.php + * + * @return int|bool + */ + protected function streamSetChunkSize() + { + if (!is_resource($this->resource)) { + throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource'); + } + + if (null === $this->chunkSize) { + throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set'); + } + + return stream_set_chunk_size($this->resource, $this->chunkSize); + } + + /** + * Wrapper to allow mocking + * + * @return int|bool + */ + protected function fwrite(string $data) + { + if (!is_resource($this->resource)) { + throw new \LogicException('fwrite called but $this->resource is not a resource'); + } + + return @fwrite($this->resource, $data); + } + + /** + * Wrapper to allow mocking + * + * @return mixed[]|bool + */ + protected function streamGetMetadata() + { + if (!is_resource($this->resource)) { + throw new \LogicException('streamGetMetadata called but $this->resource is not a resource'); + } + + return stream_get_meta_data($this->resource); + } + + private function validateTimeout(float $value): void + { + if ($value < 0) { + throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)"); + } + } + + private function connectIfNotConnected(): void + { + if ($this->isConnected()) { + return; + } + $this->connect(); + } + + /** + * @phpstan-param FormattedRecord $record + */ + protected function generateDataStream(array $record): string + { + return (string) $record['formatted']; + } + + /** + * @return resource|null + */ + protected function getResource() + { + return $this->resource; + } + + private function connect(): void + { + $this->createSocketResource(); + $this->setSocketTimeout(); + $this->setStreamChunkSize(); + } + + private function createSocketResource(): void + { + if ($this->isPersistent()) { + $resource = $this->pfsockopen(); + } else { + $resource = $this->fsockopen(); + } + if (is_bool($resource)) { + throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); + } + $this->resource = $resource; + } + + private function setSocketTimeout(): void + { + if (!$this->streamSetTimeout()) { + throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); + } + } + + private function setStreamChunkSize(): void + { + if ($this->chunkSize && !$this->streamSetChunkSize()) { + throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()"); + } + } + + private function writeToSocket(string $data): void + { + $length = strlen($data); + $sent = 0; + $this->lastSentBytes = $sent; + while ($this->isConnected() && $sent < $length) { + if (0 == $sent) { + $chunk = $this->fwrite($data); + } else { + $chunk = $this->fwrite(substr($data, $sent)); + } + if ($chunk === false) { + throw new \RuntimeException("Could not write to socket"); + } + $sent += $chunk; + $socketInfo = $this->streamGetMetadata(); + if (is_array($socketInfo) && $socketInfo['timed_out']) { + throw new \RuntimeException("Write timed-out"); + } + + if ($this->writingIsTimedOut($sent)) { + throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent $sent of $length)"); + } + } + if (!$this->isConnected() && $sent < $length) { + throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + } + } + + private function writingIsTimedOut(int $sent): bool + { + // convert to ms + if (0.0 == $this->writingTimeout) { + return false; + } + + if ($sent !== $this->lastSentBytes) { + $this->lastWritingAt = microtime(true); + $this->lastSentBytes = $sent; + + return false; + } else { + usleep(100); + } + + if ((microtime(true) - $this->lastWritingAt) >= $this->writingTimeout) { + $this->closeSocket(); + + return true; + } + + return false; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php new file mode 100644 index 0000000..dcf282b --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.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 Monolog\Handler; + +use Aws\Sqs\SqsClient; +use Monolog\Logger; +use Monolog\Utils; + +/** + * Writes to any sqs queue. + * + * @author Martijn van Calker + */ +class SqsHandler extends AbstractProcessingHandler +{ + /** 256 KB in bytes - maximum message size in SQS */ + protected const MAX_MESSAGE_SIZE = 262144; + /** 100 KB in bytes - head message size for new error log */ + protected const HEAD_MESSAGE_SIZE = 102400; + + /** @var SqsClient */ + private $client; + /** @var string */ + private $queueUrl; + + public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true) + { + parent::__construct($level, $bubble); + + $this->client = $sqsClient; + $this->queueUrl = $queueUrl; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) { + throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record)); + } + + $messageBody = $record['formatted']; + if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) { + $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE); + } + + $this->client->sendMessage([ + 'QueueUrl' => $this->queueUrl, + 'MessageBody' => $messageBody, + ]); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php new file mode 100644 index 0000000..82c048e --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -0,0 +1,224 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; + +/** + * Stores to any stream resource + * + * Can be used to store into php://stderr, remote and local files, etc. + * + * @author Jordi Boggiano + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class StreamHandler extends AbstractProcessingHandler +{ + /** @const int */ + protected const MAX_CHUNK_SIZE = 2147483647; + /** @const int 10MB */ + protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024; + /** @var int */ + protected $streamChunkSize; + /** @var resource|null */ + protected $stream; + /** @var ?string */ + protected $url = null; + /** @var ?string */ + private $errorMessage = null; + /** @var ?int */ + protected $filePermission; + /** @var bool */ + protected $useLocking; + /** @var true|null */ + private $dirCreated = null; + + /** + * @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write + * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param bool $useLocking Try to lock log file before doing any writes + * + * @throws \InvalidArgumentException If stream is not a resource or string + */ + public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) + { + parent::__construct($level, $bubble); + + if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) { + if ($phpMemoryLimit > 0) { + // use max 10% of allowed memory for the chunk size, and at least 100KB + $this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024)); + } else { + // memory is unlimited, set to the default 10MB + $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE; + } + } else { + // no memory limit information, set to the default 10MB + $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE; + } + + if (is_resource($stream)) { + $this->stream = $stream; + + stream_set_chunk_size($this->stream, $this->streamChunkSize); + } elseif (is_string($stream)) { + $this->url = Utils::canonicalizePath($stream); + } else { + throw new \InvalidArgumentException('A stream must either be a resource or a string.'); + } + + $this->filePermission = $filePermission; + $this->useLocking = $useLocking; + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + if ($this->url && is_resource($this->stream)) { + fclose($this->stream); + } + $this->stream = null; + $this->dirCreated = null; + } + + /** + * Return the currently active stream if it is open + * + * @return resource|null + */ + public function getStream() + { + return $this->stream; + } + + /** + * Return the stream URL if it was configured with a URL and not an active resource + * + * @return string|null + */ + public function getUrl(): ?string + { + return $this->url; + } + + /** + * @return int + */ + public function getStreamChunkSize(): int + { + return $this->streamChunkSize; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if (!is_resource($this->stream)) { + $url = $this->url; + if (null === $url || '' === $url) { + throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().' . Utils::getRecordMessageForException($record)); + } + $this->createDir($url); + $this->errorMessage = null; + set_error_handler([$this, 'customErrorHandler']); + try { + $stream = fopen($url, 'a'); + if ($this->filePermission !== null) { + @chmod($url, $this->filePermission); + } + } finally { + restore_error_handler(); + } + if (!is_resource($stream)) { + $this->stream = null; + + throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $url) . Utils::getRecordMessageForException($record)); + } + stream_set_chunk_size($stream, $this->streamChunkSize); + $this->stream = $stream; + } + + $stream = $this->stream; + if (!is_resource($stream)) { + throw new \LogicException('No stream was opened yet' . Utils::getRecordMessageForException($record)); + } + + if ($this->useLocking) { + // ignoring errors here, there's not much we can do about them + flock($stream, LOCK_EX); + } + + $this->streamWrite($stream, $record); + + if ($this->useLocking) { + flock($stream, LOCK_UN); + } + } + + /** + * Write to stream + * @param resource $stream + * @param array $record + * + * @phpstan-param FormattedRecord $record + */ + protected function streamWrite($stream, array $record): void + { + fwrite($stream, (string) $record['formatted']); + } + + private function customErrorHandler(int $code, string $msg): bool + { + $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg); + + return true; + } + + private function getDirFromStream(string $stream): ?string + { + $pos = strpos($stream, '://'); + if ($pos === false) { + return dirname($stream); + } + + if ('file://' === substr($stream, 0, 7)) { + return dirname(substr($stream, 7)); + } + + return null; + } + + private function createDir(string $url): void + { + // Do not try to create dir if it has already been tried. + if ($this->dirCreated) { + return; + } + + $dir = $this->getDirFromStream($url); + if (null !== $dir && !is_dir($dir)) { + $this->errorMessage = null; + set_error_handler([$this, 'customErrorHandler']); + $status = mkdir($dir, 0777, true); + restore_error_handler(); + if (false === $status && !is_dir($dir) && strpos((string) $this->errorMessage, 'File exists') === false) { + throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: '.$this->errorMessage, $dir)); + } + } + $this->dirCreated = true; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php new file mode 100644 index 0000000..fae9251 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; +use Swift_Message; +use Swift; + +/** + * SwiftMailerHandler uses Swift_Mailer to send the emails + * + * @author Gyula Sallai + * + * @phpstan-import-type Record from \Monolog\Logger + * @deprecated Since Monolog 2.6. Use SymfonyMailerHandler instead. + */ +class SwiftMailerHandler extends MailHandler +{ + /** @var \Swift_Mailer */ + protected $mailer; + /** @var Swift_Message|callable(string, Record[]): Swift_Message */ + private $messageTemplate; + + /** + * @psalm-param Swift_Message|callable(string, Record[]): Swift_Message $message + * + * @param \Swift_Mailer $mailer The mailer to use + * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced + */ + public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true) + { + parent::__construct($level, $bubble); + + @trigger_error('The SwiftMailerHandler is deprecated since Monolog 2.6. Use SymfonyMailerHandler instead.', E_USER_DEPRECATED); + + $this->mailer = $mailer; + $this->messageTemplate = $message; + } + + /** + * {@inheritDoc} + */ + protected function send(string $content, array $records): void + { + $this->mailer->send($this->buildMessage($content, $records)); + } + + /** + * Gets the formatter for the Swift_Message subject. + * + * @param string|null $format The format of the subject + */ + protected function getSubjectFormatter(?string $format): FormatterInterface + { + return new LineFormatter($format); + } + + /** + * Creates instance of Swift_Message to be sent + * + * @param string $content formatted email body to be sent + * @param array $records Log records that formed the content + * @return Swift_Message + * + * @phpstan-param Record[] $records + */ + protected function buildMessage(string $content, array $records): Swift_Message + { + $message = null; + if ($this->messageTemplate instanceof Swift_Message) { + $message = clone $this->messageTemplate; + $message->generateId(); + } elseif (is_callable($this->messageTemplate)) { + $message = ($this->messageTemplate)($content, $records); + } + + if (!$message instanceof Swift_Message) { + $record = reset($records); + throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : '')); + } + + if ($records) { + $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); + $message->setSubject($subjectFormatter->format($this->getHighestRecord($records))); + } + + $mime = 'text/plain'; + if ($this->isHtmlBody($content)) { + $mime = 'text/html'; + } + + $message->setBody($content, $mime); + /** @phpstan-ignore-next-line */ + if (version_compare(Swift::VERSION, '6.0.0', '>=')) { + $message->setDate(new \DateTimeImmutable()); + } else { + /** @phpstan-ignore-next-line */ + $message->setDate(time()); + } + + return $message; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php new file mode 100644 index 0000000..130e6f1 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; +use Symfony\Component\Mailer\MailerInterface; +use Symfony\Component\Mailer\Transport\TransportInterface; +use Symfony\Component\Mime\Email; + +/** + * SymfonyMailerHandler uses Symfony's Mailer component to send the emails + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class SymfonyMailerHandler extends MailHandler +{ + /** @var MailerInterface|TransportInterface */ + protected $mailer; + /** @var Email|callable(string, Record[]): Email */ + private $emailTemplate; + + /** + * @psalm-param Email|callable(string, Record[]): Email $email + * + * @param MailerInterface|TransportInterface $mailer The mailer to use + * @param callable|Email $email An email template, the subject/body will be replaced + */ + public function __construct($mailer, $email, $level = Logger::ERROR, bool $bubble = true) + { + parent::__construct($level, $bubble); + + $this->mailer = $mailer; + $this->emailTemplate = $email; + } + + /** + * {@inheritDoc} + */ + protected function send(string $content, array $records): void + { + $this->mailer->send($this->buildMessage($content, $records)); + } + + /** + * Gets the formatter for the Swift_Message subject. + * + * @param string|null $format The format of the subject + */ + protected function getSubjectFormatter(?string $format): FormatterInterface + { + return new LineFormatter($format); + } + + /** + * Creates instance of Email to be sent + * + * @param string $content formatted email body to be sent + * @param array $records Log records that formed the content + * + * @phpstan-param Record[] $records + */ + protected function buildMessage(string $content, array $records): Email + { + $message = null; + if ($this->emailTemplate instanceof Email) { + $message = clone $this->emailTemplate; + } elseif (is_callable($this->emailTemplate)) { + $message = ($this->emailTemplate)($content, $records); + } + + if (!$message instanceof Email) { + $record = reset($records); + throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : '')); + } + + if ($records) { + $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); + $message->subject($subjectFormatter->format($this->getHighestRecord($records))); + } + + if ($this->isHtmlBody($content)) { + if (null !== ($charset = $message->getHtmlCharset())) { + $message->html($content, $charset); + } else { + $message->html($content); + } + } else { + if (null !== ($charset = $message->getTextCharset())) { + $message->text($content, $charset); + } else { + $message->text($content); + } + } + + return $message->date(new \DateTimeImmutable()); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php new file mode 100644 index 0000000..1d543b7 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Monolog\Utils; + +/** + * Logs to syslog service. + * + * usage example: + * + * $log = new Logger('application'); + * $syslog = new SyslogHandler('myfacility', 'local6'); + * $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); + * $syslog->setFormatter($formatter); + * $log->pushHandler($syslog); + * + * @author Sven Paulus + */ +class SyslogHandler extends AbstractSyslogHandler +{ + /** @var string */ + protected $ident; + /** @var int */ + protected $logopts; + + /** + * @param string $ident + * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant + * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID + */ + public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID) + { + parent::__construct($facility, $level, $bubble); + + $this->ident = $ident; + $this->logopts = $logopts; + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + closelog(); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + if (!openlog($this->ident, $this->logopts, $this->facility)) { + throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"' . Utils::getRecordMessageForException($record)); + } + syslog($this->logLevels[$record['level']], (string) $record['formatted']); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php new file mode 100644 index 0000000..dbd8ef6 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.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 Monolog\Handler\SyslogUdp; + +use Monolog\Utils; +use Socket; + +class UdpSocket +{ + protected const DATAGRAM_MAX_LENGTH = 65023; + + /** @var string */ + protected $ip; + /** @var int */ + protected $port; + /** @var resource|Socket|null */ + protected $socket = null; + + public function __construct(string $ip, int $port = 514) + { + $this->ip = $ip; + $this->port = $port; + } + + /** + * @param string $line + * @param string $header + * @return void + */ + public function write($line, $header = "") + { + $this->send($this->assembleMessage($line, $header)); + } + + public function close(): void + { + if (is_resource($this->socket) || $this->socket instanceof Socket) { + socket_close($this->socket); + $this->socket = null; + } + } + + /** + * @return resource|Socket + */ + protected function getSocket() + { + if (null !== $this->socket) { + return $this->socket; + } + + $domain = AF_INET; + $protocol = SOL_UDP; + // Check if we are using unix sockets. + if ($this->port === 0) { + $domain = AF_UNIX; + $protocol = IPPROTO_IP; + } + + $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null; + if (null === $this->socket) { + throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' could not be opened via socket_create'); + } + + return $this->socket; + } + + protected function send(string $chunk): void + { + socket_sendto($this->getSocket(), $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); + } + + protected function assembleMessage(string $line, string $header): string + { + $chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header); + + return $header . Utils::substr($line, 0, $chunkSize); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php new file mode 100644 index 0000000..deaa19f --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.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 Monolog\Handler; + +use DateTimeInterface; +use Monolog\Logger; +use Monolog\Handler\SyslogUdp\UdpSocket; +use Monolog\Utils; + +/** + * A Handler for logging to a remote syslogd server. + * + * @author Jesper Skovgaard Nielsen + * @author Dominik Kukacka + */ +class SyslogUdpHandler extends AbstractSyslogHandler +{ + const RFC3164 = 0; + const RFC5424 = 1; + const RFC5424e = 2; + + /** @var array */ + private $dateFormats = array( + self::RFC3164 => 'M d H:i:s', + self::RFC5424 => \DateTime::RFC3339, + self::RFC5424e => \DateTime::RFC3339_EXTENDED, + ); + + /** @var UdpSocket */ + protected $socket; + /** @var string */ + protected $ident; + /** @var self::RFC* */ + protected $rfc; + + /** + * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then) + * @param int $port Port number, or 0 if $host is a unix socket + * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $ident Program name or tag for each log message. + * @param int $rfc RFC to format the message for. + * @throws MissingExtensionException + * + * @phpstan-param self::RFC* $rfc + */ + public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424) + { + if (!extension_loaded('sockets')) { + throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler'); + } + + parent::__construct($facility, $level, $bubble); + + $this->ident = $ident; + $this->rfc = $rfc; + + $this->socket = new UdpSocket($host, $port); + } + + protected function write(array $record): void + { + $lines = $this->splitMessageIntoLines($record['formatted']); + + $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']); + + foreach ($lines as $line) { + $this->socket->write($line, $header); + } + } + + public function close(): void + { + $this->socket->close(); + } + + /** + * @param string|string[] $message + * @return string[] + */ + private function splitMessageIntoLines($message): array + { + if (is_array($message)) { + $message = implode("\n", $message); + } + + $lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY); + if (false === $lines) { + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); + } + + return $lines; + } + + /** + * Make common syslog header (see rfc5424 or rfc3164) + */ + protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime): string + { + $priority = $severity + $this->facility; + + if (!$pid = getmypid()) { + $pid = '-'; + } + + if (!$hostname = gethostname()) { + $hostname = '-'; + } + + if ($this->rfc === self::RFC3164) { + // see https://github.com/phpstan/phpstan/issues/5348 + // @phpstan-ignore-next-line + $dateNew = $datetime->setTimezone(new \DateTimeZone('UTC')); + $date = $dateNew->format($this->dateFormats[$this->rfc]); + + return "<$priority>" . + $date . " " . + $hostname . " " . + $this->ident . "[" . $pid . "]: "; + } + + $date = $datetime->format($this->dateFormats[$this->rfc]); + + return "<$priority>1 " . + $date . " " . + $hostname . " " . + $this->ident . " " . + $pid . " - - "; + } + + /** + * Inject your own socket, mainly used for testing + */ + public function setSocket(UdpSocket $socket): self + { + $this->socket = $socket; + + return $this; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php new file mode 100644 index 0000000..8912eba --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php @@ -0,0 +1,274 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use RuntimeException; +use Monolog\Logger; +use Monolog\Utils; + +/** + * Handler send logs to Telegram using Telegram Bot API. + * + * How to use: + * 1) Create telegram bot with https://telegram.me/BotFather + * 2) Create a telegram channel where logs will be recorded. + * 3) Add created bot from step 1 to the created channel from step 2. + * + * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler + * + * @link https://core.telegram.org/bots/api + * + * @author Mazur Alexandr + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class TelegramBotHandler extends AbstractProcessingHandler +{ + private const BOT_API = 'https://api.telegram.org/bot'; + + /** + * The available values of parseMode according to the Telegram api documentation + */ + private const AVAILABLE_PARSE_MODES = [ + 'HTML', + 'MarkdownV2', + 'Markdown', // legacy mode without underline and strikethrough, use MarkdownV2 instead + ]; + + /** + * The maximum number of characters allowed in a message according to the Telegram api documentation + */ + private const MAX_MESSAGE_LENGTH = 4096; + + /** + * Telegram bot access token provided by BotFather. + * Create telegram bot with https://telegram.me/BotFather and use access token from it. + * @var string + */ + private $apiKey; + + /** + * Telegram channel name. + * Since to start with '@' symbol as prefix. + * @var string + */ + private $channel; + + /** + * The kind of formatting that is used for the message. + * See available options at https://core.telegram.org/bots/api#formatting-options + * or in AVAILABLE_PARSE_MODES + * @var ?string + */ + private $parseMode; + + /** + * Disables link previews for links in the message. + * @var ?bool + */ + private $disableWebPagePreview; + + /** + * Sends the message silently. Users will receive a notification with no sound. + * @var ?bool + */ + private $disableNotification; + + /** + * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages. + * False - truncates a message that is too long. + * @var bool + */ + private $splitLongMessages; + + /** + * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests). + * @var bool + */ + private $delayBetweenMessages; + + /** + * @param string $apiKey Telegram bot access token provided by BotFather + * @param string $channel Telegram channel name + * @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages + * @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API + * @throws MissingExtensionException + */ + public function __construct( + string $apiKey, + string $channel, + $level = Logger::DEBUG, + bool $bubble = true, + string $parseMode = null, + bool $disableWebPagePreview = null, + bool $disableNotification = null, + bool $splitLongMessages = false, + bool $delayBetweenMessages = false + ) + { + if (!extension_loaded('curl')) { + throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler'); + } + + parent::__construct($level, $bubble); + + $this->apiKey = $apiKey; + $this->channel = $channel; + $this->setParseMode($parseMode); + $this->disableWebPagePreview($disableWebPagePreview); + $this->disableNotification($disableNotification); + $this->splitLongMessages($splitLongMessages); + $this->delayBetweenMessages($delayBetweenMessages); + } + + public function setParseMode(string $parseMode = null): self + { + if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) { + throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.'); + } + + $this->parseMode = $parseMode; + + return $this; + } + + public function disableWebPagePreview(bool $disableWebPagePreview = null): self + { + $this->disableWebPagePreview = $disableWebPagePreview; + + return $this; + } + + public function disableNotification(bool $disableNotification = null): self + { + $this->disableNotification = $disableNotification; + + return $this; + } + + /** + * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages. + * False - truncates a message that is too long. + * @param bool $splitLongMessages + * @return $this + */ + public function splitLongMessages(bool $splitLongMessages = false): self + { + $this->splitLongMessages = $splitLongMessages; + + return $this; + } + + /** + * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests). + * @param bool $delayBetweenMessages + * @return $this + */ + public function delayBetweenMessages(bool $delayBetweenMessages = false): self + { + $this->delayBetweenMessages = $delayBetweenMessages; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + /** @var Record[] $messages */ + $messages = []; + + foreach ($records as $record) { + if (!$this->isHandling($record)) { + continue; + } + + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + $messages[] = $record; + } + + if (!empty($messages)) { + $this->send((string)$this->getFormatter()->formatBatch($messages)); + } + } + + /** + * @inheritDoc + */ + protected function write(array $record): void + { + $this->send($record['formatted']); + } + + /** + * Send request to @link https://api.telegram.org/bot on SendMessage action. + * @param string $message + */ + protected function send(string $message): void + { + $messages = $this->handleMessageLength($message); + + foreach ($messages as $key => $msg) { + if ($this->delayBetweenMessages && $key > 0) { + sleep(1); + } + + $this->sendCurl($msg); + } + } + + protected function sendCurl(string $message): void + { + $ch = curl_init(); + $url = self::BOT_API . $this->apiKey . '/SendMessage'; + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ + 'text' => $message, + 'chat_id' => $this->channel, + 'parse_mode' => $this->parseMode, + 'disable_web_page_preview' => $this->disableWebPagePreview, + 'disable_notification' => $this->disableNotification, + ])); + + $result = Curl\Util::execute($ch); + if (!is_string($result)) { + throw new RuntimeException('Telegram API error. Description: No response'); + } + $result = json_decode($result, true); + + if ($result['ok'] === false) { + throw new RuntimeException('Telegram API error. Description: ' . $result['description']); + } + } + + /** + * Handle a message that is too long: truncates or splits into several + * @param string $message + * @return string[] + */ + private function handleMessageLength(string $message): array + { + $truncatedMarker = ' (...truncated)'; + if (!$this->splitLongMessages && strlen($message) > self::MAX_MESSAGE_LENGTH) { + return [Utils::substr($message, 0, self::MAX_MESSAGE_LENGTH - strlen($truncatedMarker)) . $truncatedMarker]; + } + + return str_split($message, self::MAX_MESSAGE_LENGTH); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php new file mode 100644 index 0000000..0986da2 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.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 Monolog\Handler; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Used for testing purposes. + * + * It records all records and gives you access to them for verification. + * + * @author Jordi Boggiano + * + * @method bool hasEmergency($record) + * @method bool hasAlert($record) + * @method bool hasCritical($record) + * @method bool hasError($record) + * @method bool hasWarning($record) + * @method bool hasNotice($record) + * @method bool hasInfo($record) + * @method bool hasDebug($record) + * + * @method bool hasEmergencyRecords() + * @method bool hasAlertRecords() + * @method bool hasCriticalRecords() + * @method bool hasErrorRecords() + * @method bool hasWarningRecords() + * @method bool hasNoticeRecords() + * @method bool hasInfoRecords() + * @method bool hasDebugRecords() + * + * @method bool hasEmergencyThatContains($message) + * @method bool hasAlertThatContains($message) + * @method bool hasCriticalThatContains($message) + * @method bool hasErrorThatContains($message) + * @method bool hasWarningThatContains($message) + * @method bool hasNoticeThatContains($message) + * @method bool hasInfoThatContains($message) + * @method bool hasDebugThatContains($message) + * + * @method bool hasEmergencyThatMatches($message) + * @method bool hasAlertThatMatches($message) + * @method bool hasCriticalThatMatches($message) + * @method bool hasErrorThatMatches($message) + * @method bool hasWarningThatMatches($message) + * @method bool hasNoticeThatMatches($message) + * @method bool hasInfoThatMatches($message) + * @method bool hasDebugThatMatches($message) + * + * @method bool hasEmergencyThatPasses($message) + * @method bool hasAlertThatPasses($message) + * @method bool hasCriticalThatPasses($message) + * @method bool hasErrorThatPasses($message) + * @method bool hasWarningThatPasses($message) + * @method bool hasNoticeThatPasses($message) + * @method bool hasInfoThatPasses($message) + * @method bool hasDebugThatPasses($message) + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class TestHandler extends AbstractProcessingHandler +{ + /** @var Record[] */ + protected $records = []; + /** @var array */ + protected $recordsByLevel = []; + /** @var bool */ + private $skipReset = false; + + /** + * @return array + * + * @phpstan-return Record[] + */ + public function getRecords() + { + return $this->records; + } + + /** + * @return void + */ + public function clear() + { + $this->records = []; + $this->recordsByLevel = []; + } + + /** + * @return void + */ + public function reset() + { + if (!$this->skipReset) { + $this->clear(); + } + } + + /** + * @return void + */ + public function setSkipReset(bool $skipReset) + { + $this->skipReset = $skipReset; + } + + /** + * @param string|int $level Logging level value or name + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecords($level): bool + { + return isset($this->recordsByLevel[Logger::toMonologLevel($level)]); + } + + /** + * @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records + * @param string|int $level Logging level value or name + * + * @phpstan-param array{message: string, context?: mixed[]}|string $record + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecord($record, $level): bool + { + if (is_string($record)) { + $record = array('message' => $record); + } + + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + + return true; + }, $level); + } + + /** + * @param string|int $level Logging level value or name + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecordThatContains(string $message, $level): bool + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + /** + * @param string|int $level Logging level value or name + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecordThatMatches(string $regex, $level): bool + { + return $this->hasRecordThatPasses(function (array $rec) use ($regex): bool { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + /** + * @param string|int $level Logging level value or name + * @return bool + * + * @psalm-param callable(Record, int): mixed $predicate + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecordThatPasses(callable $predicate, $level) + { + $level = Logger::toMonologLevel($level); + + if (!isset($this->recordsByLevel[$level])) { + return false; + } + + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if ($predicate($rec, $i)) { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + /** + * @param string $method + * @param mixed[] $args + * @return bool + */ + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = constant('Monolog\Logger::' . strtoupper($matches[2])); + $callback = [$this, $genericMethod]; + if (is_callable($callback)) { + $args[] = $level; + + return call_user_func_array($callback, $args); + } + } + + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php new file mode 100644 index 0000000..c818352 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.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 Monolog\Handler; + +trait WebRequestRecognizerTrait +{ + /** + * Checks if PHP's serving a web request + * @return bool + */ + protected function isWebRequest(): bool + { + return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php new file mode 100644 index 0000000..b6d3d3b --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.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 Monolog\Handler; + +/** + * Forwards records to multiple handlers suppressing failures of each handler + * and continuing through to give every handler a chance to succeed. + * + * @author Craig D'Amelio + * + * @phpstan-import-type Record from \Monolog\Logger + */ +class WhatFailureGroupHandler extends GroupHandler +{ + /** + * {@inheritDoc} + */ + public function handle(array $record): bool + { + if ($this->processors) { + /** @var Record $record */ + $record = $this->processRecord($record); + } + + foreach ($this->handlers as $handler) { + try { + $handler->handle($record); + } catch (\Throwable $e) { + // What failure? + } + } + + return false === $this->bubble; + } + + /** + * {@inheritDoc} + */ + public function handleBatch(array $records): void + { + if ($this->processors) { + $processed = array(); + foreach ($records as $record) { + $processed[] = $this->processRecord($record); + } + /** @var Record[] $records */ + $records = $processed; + } + + foreach ($this->handlers as $handler) { + try { + $handler->handleBatch($records); + } catch (\Throwable $e) { + // What failure? + } + } + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + foreach ($this->handlers as $handler) { + try { + $handler->close(); + } catch (\Throwable $e) { + // What failure? + } + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php new file mode 100644 index 0000000..ddd46d8 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.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 Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\NormalizerFormatter; +use Monolog\Logger; + +/** + * Handler sending logs to Zend Monitor + * + * @author Christian Bergau + * @author Jason Davis + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + */ +class ZendMonitorHandler extends AbstractProcessingHandler +{ + /** + * Monolog level / ZendMonitor Custom Event priority map + * + * @var array + */ + protected $levelMap = []; + + /** + * @throws MissingExtensionException + */ + public function __construct($level = Logger::DEBUG, bool $bubble = true) + { + if (!function_exists('zend_monitor_custom_event')) { + throw new MissingExtensionException( + 'You must have Zend Server installed with Zend Monitor enabled in order to use this handler' + ); + } + //zend monitor constants are not defined if zend monitor is not enabled. + $this->levelMap = [ + Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, + Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + ]; + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $this->writeZendMonitorCustomEvent( + Logger::getLevelName($record['level']), + $record['message'], + $record['formatted'], + $this->levelMap[$record['level']] + ); + } + + /** + * Write to Zend Monitor Events + * @param string $type Text displayed in "Class Name (custom)" field + * @param string $message Text displayed in "Error String" + * @param array $formatted Displayed in Custom Variables tab + * @param int $severity Set the event severity level (-1,0,1) + * + * @phpstan-param FormattedRecord $formatted + */ + protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity): void + { + zend_monitor_custom_event($type, $message, $formatted, $severity); + } + + /** + * {@inheritDoc} + */ + public function getDefaultFormatter(): FormatterInterface + { + return new NormalizerFormatter(); + } + + /** + * @return array + */ + public function getLevelMap(): array + { + return $this->levelMap; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/LogRecord.php b/cacme/vendor/monolog/monolog/src/Monolog/LogRecord.php new file mode 100644 index 0000000..702807d --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/LogRecord.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 Monolog; + +use ArrayAccess; + +/** + * Monolog log record interface for forward compatibility with Monolog 3.0 + * + * This is just present in Monolog 2.4+ to allow interoperable code to be written against + * both versions by type-hinting arguments as `array|\Monolog\LogRecord $record` + * + * Do not rely on this interface for other purposes, and do not implement it. + * + * @author Jordi Boggiano + * @template-extends \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', mixed> + * @phpstan-import-type Record from Logger + */ +interface LogRecord extends \ArrayAccess +{ + /** + * @phpstan-return Record + */ + public function toArray(): array; +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Logger.php b/cacme/vendor/monolog/monolog/src/Monolog/Logger.php new file mode 100644 index 0000000..84a2f55 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Logger.php @@ -0,0 +1,761 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use DateTimeZone; +use Monolog\Handler\HandlerInterface; +use Psr\Log\LoggerInterface; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; +use Throwable; +use Stringable; + +/** + * Monolog log channel + * + * It contains a stack of Handlers and a stack of Processors, + * and uses them to store records that are added to it. + * + * @author Jordi Boggiano + * + * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY + * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY' + * @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]} + */ +class Logger implements LoggerInterface, ResettableInterface +{ + /** + * Detailed debug information + */ + public const DEBUG = 100; + + /** + * Interesting events + * + * Examples: User logs in, SQL logs. + */ + public const INFO = 200; + + /** + * Uncommon events + */ + public const NOTICE = 250; + + /** + * Exceptional occurrences that are not errors + * + * Examples: Use of deprecated APIs, poor use of an API, + * undesirable things that are not necessarily wrong. + */ + public const WARNING = 300; + + /** + * Runtime errors + */ + public const ERROR = 400; + + /** + * Critical conditions + * + * Example: Application component unavailable, unexpected exception. + */ + public const CRITICAL = 500; + + /** + * Action must be taken immediately + * + * Example: Entire website down, database unavailable, etc. + * This should trigger the SMS alerts and wake you up. + */ + public const ALERT = 550; + + /** + * Urgent alert. + */ + public const EMERGENCY = 600; + + /** + * Monolog API version + * + * This is only bumped when API breaks are done and should + * follow the major version of the library + * + * @var int + */ + public const API = 2; + + /** + * This is a static variable and not a constant to serve as an extension point for custom levels + * + * @var array $levels Logging levels with the levels as key + * + * @phpstan-var array $levels Logging levels with the levels as key + */ + protected static $levels = [ + self::DEBUG => 'DEBUG', + self::INFO => 'INFO', + self::NOTICE => 'NOTICE', + self::WARNING => 'WARNING', + self::ERROR => 'ERROR', + self::CRITICAL => 'CRITICAL', + self::ALERT => 'ALERT', + self::EMERGENCY => 'EMERGENCY', + ]; + + /** + * Mapping between levels numbers defined in RFC 5424 and Monolog ones + * + * @phpstan-var array $rfc_5424_levels + */ + private const RFC_5424_LEVELS = [ + 7 => self::DEBUG, + 6 => self::INFO, + 5 => self::NOTICE, + 4 => self::WARNING, + 3 => self::ERROR, + 2 => self::CRITICAL, + 1 => self::ALERT, + 0 => self::EMERGENCY, + ]; + + /** + * @var string + */ + protected $name; + + /** + * The handler stack + * + * @var HandlerInterface[] + */ + protected $handlers; + + /** + * Processors that will process all log records + * + * To process records of a single handler instead, add the processor on that specific handler + * + * @var callable[] + */ + protected $processors; + + /** + * @var bool + */ + protected $microsecondTimestamps = true; + + /** + * @var DateTimeZone + */ + protected $timezone; + + /** + * @var callable|null + */ + protected $exceptionHandler; + + /** + * @var int Keeps track of depth to prevent infinite logging loops + */ + private $logDepth = 0; + + /** + * @var \WeakMap<\Fiber, int>|null Keeps track of depth inside fibers to prevent infinite logging loops + */ + private $fiberLogDepth; + + /** + * @var bool Whether to detect infinite logging loops + * + * This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this + */ + private $detectCycles = true; + + /** + * @psalm-param array $processors + * + * @param string $name The logging channel, a simple descriptive name that is attached to all log records + * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. + * @param callable[] $processors Optional array of processors + * @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used + */ + public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null) + { + $this->name = $name; + $this->setHandlers($handlers); + $this->processors = $processors; + $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC'); + + if (\PHP_VERSION_ID >= 80100) { + // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 + /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ + $fiberLogDepth = new \WeakMap(); + $this->fiberLogDepth = $fiberLogDepth; + } + } + + public function getName(): string + { + return $this->name; + } + + /** + * Return a new cloned instance with the name changed + */ + public function withName(string $name): self + { + $new = clone $this; + $new->name = $name; + + return $new; + } + + /** + * Pushes a handler on to the stack. + */ + public function pushHandler(HandlerInterface $handler): self + { + array_unshift($this->handlers, $handler); + + return $this; + } + + /** + * Pops a handler from the stack + * + * @throws \LogicException If empty handler stack + */ + public function popHandler(): HandlerInterface + { + if (!$this->handlers) { + throw new \LogicException('You tried to pop from an empty handler stack.'); + } + + return array_shift($this->handlers); + } + + /** + * Set handlers, replacing all existing ones. + * + * If a map is passed, keys will be ignored. + * + * @param HandlerInterface[] $handlers + */ + public function setHandlers(array $handlers): self + { + $this->handlers = []; + foreach (array_reverse($handlers) as $handler) { + $this->pushHandler($handler); + } + + return $this; + } + + /** + * @return HandlerInterface[] + */ + public function getHandlers(): array + { + return $this->handlers; + } + + /** + * Adds a processor on to the stack. + */ + public function pushProcessor(callable $callback): self + { + array_unshift($this->processors, $callback); + + return $this; + } + + /** + * Removes the processor on top of the stack and returns it. + * + * @throws \LogicException If empty processor stack + * @return callable + */ + public function popProcessor(): callable + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * @return callable[] + */ + public function getProcessors(): array + { + return $this->processors; + } + + /** + * Control the use of microsecond resolution timestamps in the 'datetime' + * member of new records. + * + * As of PHP7.1 microseconds are always included by the engine, so + * there is no performance penalty and Monolog 2 enabled microseconds + * by default. This function lets you disable them though in case you want + * to suppress microseconds from the output. + * + * @param bool $micro True to use microtime() to create timestamps + */ + public function useMicrosecondTimestamps(bool $micro): self + { + $this->microsecondTimestamps = $micro; + + return $this; + } + + public function useLoggingLoopDetection(bool $detectCycles): self + { + $this->detectCycles = $detectCycles; + + return $this; + } + + /** + * Adds a log record. + * + * @param int $level The logging level (a Monolog or RFC 5424 level) + * @param string $message The log message + * @param mixed[] $context The log context + * @param DateTimeImmutable $datetime Optional log date to log into the past or future + * @return bool Whether the record has been processed + * + * @phpstan-param Level $level + */ + public function addRecord(int $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool + { + if (isset(self::RFC_5424_LEVELS[$level])) { + $level = self::RFC_5424_LEVELS[$level]; + } + + if ($this->detectCycles) { + if (\PHP_VERSION_ID >= 80100 && $fiber = \Fiber::getCurrent()) { + $this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0; + $logDepth = ++$this->fiberLogDepth[$fiber]; + } else { + $logDepth = ++$this->logDepth; + } + } else { + $logDepth = 0; + } + + if ($logDepth === 3) { + $this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.'); + return false; + } elseif ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above + return false; + } + + try { + $record = null; + + foreach ($this->handlers as $handler) { + if (null === $record) { + // skip creating the record as long as no handler is going to handle it + if (!$handler->isHandling(['level' => $level])) { + continue; + } + + $levelName = static::getLevelName($level); + + $record = [ + 'message' => $message, + 'context' => $context, + 'level' => $level, + 'level_name' => $levelName, + 'channel' => $this->name, + 'datetime' => $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), + 'extra' => [], + ]; + + try { + foreach ($this->processors as $processor) { + $record = $processor($record); + } + } catch (Throwable $e) { + $this->handleException($e, $record); + + return true; + } + } + + // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted + try { + if (true === $handler->handle($record)) { + break; + } + } catch (Throwable $e) { + $this->handleException($e, $record); + + return true; + } + } + } finally { + if ($this->detectCycles) { + if (isset($fiber)) { + $this->fiberLogDepth[$fiber]--; + } else { + $this->logDepth--; + } + } + } + + return null !== $record; + } + + /** + * Ends a log cycle and frees all resources used by handlers. + * + * Closing a Handler means flushing all buffers and freeing any open resources/handles. + * Handlers that have been closed should be able to accept log records again and re-open + * themselves on demand, but this may not always be possible depending on implementation. + * + * This is useful at the end of a request and will be called automatically on every handler + * when they get destructed. + */ + public function close(): void + { + foreach ($this->handlers as $handler) { + $handler->close(); + } + } + + /** + * Ends a log cycle and resets all handlers and processors to their initial state. + * + * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal + * state, and getting it back to a state in which it can receive log records again. + * + * This is useful in case you want to avoid logs leaking between two requests or jobs when you + * have a long running process like a worker or an application server serving multiple requests + * in one process. + */ + public function reset(): void + { + foreach ($this->handlers as $handler) { + if ($handler instanceof ResettableInterface) { + $handler->reset(); + } + } + + foreach ($this->processors as $processor) { + if ($processor instanceof ResettableInterface) { + $processor->reset(); + } + } + } + + /** + * Gets all supported logging levels. + * + * @return array Assoc array with human-readable level names => level codes. + * @phpstan-return array + */ + public static function getLevels(): array + { + return array_flip(static::$levels); + } + + /** + * Gets the name of the logging level. + * + * @throws \Psr\Log\InvalidArgumentException If level is not defined + * + * @phpstan-param Level $level + * @phpstan-return LevelName + */ + public static function getLevelName(int $level): string + { + if (!isset(static::$levels[$level])) { + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); + } + + return static::$levels[$level]; + } + + /** + * Converts PSR-3 levels to Monolog ones if necessary + * + * @param string|int $level Level number (monolog) or name (PSR-3) + * @throws \Psr\Log\InvalidArgumentException If level is not defined + * + * @phpstan-param Level|LevelName|LogLevel::* $level + * @phpstan-return Level + */ + public static function toMonologLevel($level): int + { + if (is_string($level)) { + if (is_numeric($level)) { + /** @phpstan-ignore-next-line */ + return intval($level); + } + + // Contains chars of all log levels and avoids using strtoupper() which may have + // strange results depending on locale (for example, "i" will become "İ" in Turkish locale) + $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY'); + if (defined(__CLASS__.'::'.$upper)) { + return constant(__CLASS__ . '::' . $upper); + } + + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels)); + } + + if (!is_int($level)) { + throw new InvalidArgumentException('Level "'.var_export($level, true).'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels)); + } + + return $level; + } + + /** + * Checks whether the Logger has a handler that listens on the given level + * + * @phpstan-param Level $level + */ + public function isHandling(int $level): bool + { + $record = [ + 'level' => $level, + ]; + + foreach ($this->handlers as $handler) { + if ($handler->isHandling($record)) { + return true; + } + } + + return false; + } + + /** + * Set a custom exception handler that will be called if adding a new record fails + * + * The callable will receive an exception object and the record that failed to be logged + */ + public function setExceptionHandler(?callable $callback): self + { + $this->exceptionHandler = $callback; + + return $this; + } + + public function getExceptionHandler(): ?callable + { + return $this->exceptionHandler; + } + + /** + * Adds a log record at an arbitrary level. + * + * This method allows for compatibility with common interfaces. + * + * @param mixed $level The log level (a Monolog, PSR-3 or RFC 5424 level) + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function log($level, $message, array $context = []): void + { + if (!is_int($level) && !is_string($level)) { + throw new \InvalidArgumentException('$level is expected to be a string or int'); + } + + if (isset(self::RFC_5424_LEVELS[$level])) { + $level = self::RFC_5424_LEVELS[$level]; + } + + $level = static::toMonologLevel($level); + + $this->addRecord($level, (string) $message, $context); + } + + /** + * Adds a log record at the DEBUG level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function debug($message, array $context = []): void + { + $this->addRecord(static::DEBUG, (string) $message, $context); + } + + /** + * Adds a log record at the INFO level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function info($message, array $context = []): void + { + $this->addRecord(static::INFO, (string) $message, $context); + } + + /** + * Adds a log record at the NOTICE level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function notice($message, array $context = []): void + { + $this->addRecord(static::NOTICE, (string) $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function warning($message, array $context = []): void + { + $this->addRecord(static::WARNING, (string) $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function error($message, array $context = []): void + { + $this->addRecord(static::ERROR, (string) $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function critical($message, array $context = []): void + { + $this->addRecord(static::CRITICAL, (string) $message, $context); + } + + /** + * Adds a log record at the ALERT level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function alert($message, array $context = []): void + { + $this->addRecord(static::ALERT, (string) $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * This method allows for compatibility with common interfaces. + * + * @param string|Stringable $message The log message + * @param mixed[] $context The log context + */ + public function emergency($message, array $context = []): void + { + $this->addRecord(static::EMERGENCY, (string) $message, $context); + } + + /** + * Sets the timezone to be used for the timestamp of log records. + */ + public function setTimezone(DateTimeZone $tz): self + { + $this->timezone = $tz; + + return $this; + } + + /** + * Returns the timezone to be used for the timestamp of log records. + */ + public function getTimezone(): DateTimeZone + { + return $this->timezone; + } + + /** + * Delegates exception management to the custom exception handler, + * or throws the exception if no custom handler is set. + * + * @param array $record + * @phpstan-param Record $record + */ + protected function handleException(Throwable $e, array $record): void + { + if (!$this->exceptionHandler) { + throw $e; + } + + ($this->exceptionHandler)($e, $record); + } + + /** + * @return array + */ + public function __serialize(): array + { + return [ + 'name' => $this->name, + 'handlers' => $this->handlers, + 'processors' => $this->processors, + 'microsecondTimestamps' => $this->microsecondTimestamps, + 'timezone' => $this->timezone, + 'exceptionHandler' => $this->exceptionHandler, + 'logDepth' => $this->logDepth, + 'detectCycles' => $this->detectCycles, + ]; + } + + /** + * @param array $data + */ + public function __unserialize(array $data): void + { + foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) { + if (isset($data[$property])) { + $this->$property = $data[$property]; + } + } + + if (\PHP_VERSION_ID >= 80100) { + // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 + /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ + $fiberLogDepth = new \WeakMap(); + $this->fiberLogDepth = $fiberLogDepth; + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php new file mode 100644 index 0000000..8166bdc --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.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 Monolog\Processor; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Injects Git branch and Git commit SHA in all records + * + * @author Nick Otter + * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class GitProcessor implements ProcessorInterface +{ + /** @var int */ + private $level; + /** @var array{branch: string, commit: string}|array|null */ + private static $cache = null; + + /** + * @param string|int $level The minimum logging level at which this Processor will be triggered + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function __construct($level = Logger::DEBUG) + { + $this->level = Logger::toMonologLevel($level); + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $record['extra']['git'] = self::getGitInfo(); + + return $record; + } + + /** + * @return array{branch: string, commit: string}|array + */ + private static function getGitInfo(): array + { + if (self::$cache) { + return self::$cache; + } + + $branches = `git branch -v --no-abbrev`; + if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { + return self::$cache = [ + 'branch' => $matches[1], + 'commit' => $matches[2], + ]; + } + + return self::$cache = []; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php new file mode 100644 index 0000000..91fda7d --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.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 Monolog\Processor; + +/** + * Injects value of gethostname in all records + */ +class HostnameProcessor implements ProcessorInterface +{ + /** @var string */ + private static $host; + + public function __construct() + { + self::$host = (string) gethostname(); + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + $record['extra']['hostname'] = self::$host; + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php new file mode 100644 index 0000000..a32e76b --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.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 Monolog\Processor; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Injects line/file:class/function where the log message came from + * + * Warning: This only works if the handler processes the logs directly. + * If you put the processor on a handler that is behind a FingersCrossedHandler + * for example, the processor will only be called once the trigger level is reached, + * and all the log records will have the same file/line/.. data from the call that + * triggered the FingersCrossedHandler. + * + * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class IntrospectionProcessor implements ProcessorInterface +{ + /** @var int */ + private $level; + /** @var string[] */ + private $skipClassesPartials; + /** @var int */ + private $skipStackFramesCount; + /** @var string[] */ + private $skipFunctions = [ + 'call_user_func', + 'call_user_func_array', + ]; + + /** + * @param string|int $level The minimum logging level at which this Processor will be triggered + * @param string[] $skipClassesPartials + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0) + { + $this->level = Logger::toMonologLevel($level); + $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials); + $this->skipStackFramesCount = $skipStackFramesCount; + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + + // skip first since it's always the current method + array_shift($trace); + // the call_user_func call is also skipped + array_shift($trace); + + $i = 0; + + while ($this->isTraceClassOrSkippedFunction($trace, $i)) { + if (isset($trace[$i]['class'])) { + foreach ($this->skipClassesPartials as $part) { + if (strpos($trace[$i]['class'], $part) !== false) { + $i++; + + continue 2; + } + } + } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) { + $i++; + + continue; + } + + break; + } + + $i += $this->skipStackFramesCount; + + // we should have the call source now + $record['extra'] = array_merge( + $record['extra'], + [ + 'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, + 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, + 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, + 'callType' => isset($trace[$i]['type']) ? $trace[$i]['type'] : null, + 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, + ] + ); + + return $record; + } + + /** + * @param array[] $trace + */ + private function isTraceClassOrSkippedFunction(array $trace, int $index): bool + { + if (!isset($trace[$index])) { + return false; + } + + return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php new file mode 100644 index 0000000..37c756f --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.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 Monolog\Processor; + +/** + * Injects memory_get_peak_usage in all records + * + * @see Monolog\Processor\MemoryProcessor::__construct() for options + * @author Rob Jensen + */ +class MemoryPeakUsageProcessor extends MemoryProcessor +{ + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + $usage = memory_get_peak_usage($this->realUsage); + + if ($this->useFormatting) { + $usage = $this->formatBytes($usage); + } + + $record['extra']['memory_peak_usage'] = $usage; + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php new file mode 100644 index 0000000..227deb7 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.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 Monolog\Processor; + +/** + * Some methods that are common for all memory processors + * + * @author Rob Jensen + */ +abstract class MemoryProcessor implements ProcessorInterface +{ + /** + * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. + */ + protected $realUsage; + + /** + * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size) + */ + protected $useFormatting; + + /** + * @param bool $realUsage Set this to true to get the real size of memory allocated from system. + * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size) + */ + public function __construct(bool $realUsage = true, bool $useFormatting = true) + { + $this->realUsage = $realUsage; + $this->useFormatting = $useFormatting; + } + + /** + * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is + * + * @param int $bytes + * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as int + */ + protected function formatBytes(int $bytes) + { + if (!$this->useFormatting) { + return $bytes; + } + + if ($bytes > 1024 * 1024) { + return round($bytes / 1024 / 1024, 2).' MB'; + } elseif ($bytes > 1024) { + return round($bytes / 1024, 2).' KB'; + } + + return $bytes . ' B'; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php new file mode 100644 index 0000000..e141921 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.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 Monolog\Processor; + +/** + * Injects memory_get_usage in all records + * + * @see Monolog\Processor\MemoryProcessor::__construct() for options + * @author Rob Jensen + */ +class MemoryUsageProcessor extends MemoryProcessor +{ + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + $usage = memory_get_usage($this->realUsage); + + if ($this->useFormatting) { + $usage = $this->formatBytes($usage); + } + + $record['extra']['memory_usage'] = $usage; + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php new file mode 100644 index 0000000..d4a628f --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.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 Monolog\Processor; + +use Monolog\Logger; +use Psr\Log\LogLevel; + +/** + * Injects Hg branch and Hg revision number in all records + * + * @author Jonathan A. Schweder + * + * @phpstan-import-type LevelName from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + */ +class MercurialProcessor implements ProcessorInterface +{ + /** @var Level */ + private $level; + /** @var array{branch: string, revision: string}|array|null */ + private static $cache = null; + + /** + * @param int|string $level The minimum logging level at which this Processor will be triggered + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function __construct($level = Logger::DEBUG) + { + $this->level = Logger::toMonologLevel($level); + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $record['extra']['hg'] = self::getMercurialInfo(); + + return $record; + } + + /** + * @return array{branch: string, revision: string}|array + */ + private static function getMercurialInfo(): array + { + if (self::$cache) { + return self::$cache; + } + + $result = explode(' ', trim(`hg id -nb`)); + + if (count($result) >= 3) { + return self::$cache = [ + 'branch' => $result[1], + 'revision' => $result[2], + ]; + } + + return self::$cache = []; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php new file mode 100644 index 0000000..3b939a9 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.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 Monolog\Processor; + +/** + * Adds value of getmypid into records + * + * @author Andreas Hörnicke + */ +class ProcessIdProcessor implements ProcessorInterface +{ + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + $record['extra']['process_id'] = getmypid(); + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php new file mode 100644 index 0000000..5defb7e --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.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 Monolog\Processor; + +/** + * An optional interface to allow labelling Monolog processors. + * + * @author Nicolas Grekas + * + * @phpstan-import-type Record from \Monolog\Logger + */ +interface ProcessorInterface +{ + /** + * @return array The processed record + * + * @phpstan-param Record $record + * @phpstan-return Record + */ + public function __invoke(array $record); +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php new file mode 100644 index 0000000..e7c1217 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.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 Monolog\Processor; + +use Monolog\Utils; + +/** + * Processes a record's message according to PSR-3 rules + * + * It replaces {foo} with the value from $context['foo'] + * + * @author Jordi Boggiano + */ +class PsrLogMessageProcessor implements ProcessorInterface +{ + public const SIMPLE_DATE = "Y-m-d\TH:i:s.uP"; + + /** @var string|null */ + private $dateFormat; + + /** @var bool */ + private $removeUsedContextFields; + + /** + * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format + * @param bool $removeUsedContextFields If set to true the fields interpolated into message gets unset + */ + public function __construct(?string $dateFormat = null, bool $removeUsedContextFields = false) + { + $this->dateFormat = $dateFormat; + $this->removeUsedContextFields = $removeUsedContextFields; + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + if (false === strpos($record['message'], '{')) { + return $record; + } + + $replacements = []; + foreach ($record['context'] as $key => $val) { + $placeholder = '{' . $key . '}'; + if (strpos($record['message'], $placeholder) === false) { + continue; + } + + if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { + $replacements[$placeholder] = $val; + } elseif ($val instanceof \DateTimeInterface) { + if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) { + // handle monolog dates using __toString if no specific dateFormat was asked for + // so that it follows the useMicroseconds flag + $replacements[$placeholder] = (string) $val; + } else { + $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE); + } + } elseif ($val instanceof \UnitEnum) { + $replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name; + } elseif (is_object($val)) { + $replacements[$placeholder] = '[object '.Utils::getClass($val).']'; + } elseif (is_array($val)) { + $replacements[$placeholder] = 'array'.Utils::jsonEncode($val, null, true); + } else { + $replacements[$placeholder] = '['.gettype($val).']'; + } + + if ($this->removeUsedContextFields) { + unset($record['context'][$key]); + } + } + + $record['message'] = strtr($record['message'], $replacements); + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php new file mode 100644 index 0000000..80f1874 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.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 Monolog\Processor; + +/** + * Adds a tags array into record + * + * @author Martijn Riemers + */ +class TagProcessor implements ProcessorInterface +{ + /** @var string[] */ + private $tags; + + /** + * @param string[] $tags + */ + public function __construct(array $tags = []) + { + $this->setTags($tags); + } + + /** + * @param string[] $tags + */ + public function addTags(array $tags = []): self + { + $this->tags = array_merge($this->tags, $tags); + + return $this; + } + + /** + * @param string[] $tags + */ + public function setTags(array $tags = []): self + { + $this->tags = $tags; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + $record['extra']['tags'] = $this->tags; + + return $record; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php new file mode 100644 index 0000000..a27b74d --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.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 Monolog\Processor; + +use Monolog\ResettableInterface; + +/** + * Adds a unique identifier into records + * + * @author Simon Mönch + */ +class UidProcessor implements ProcessorInterface, ResettableInterface +{ + /** @var string */ + private $uid; + + public function __construct(int $length = 7) + { + if ($length > 32 || $length < 1) { + throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); + } + + $this->uid = $this->generateUid($length); + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + $record['extra']['uid'] = $this->uid; + + return $record; + } + + public function getUid(): string + { + return $this->uid; + } + + public function reset() + { + $this->uid = $this->generateUid(strlen($this->uid)); + } + + private function generateUid(int $length): string + { + return substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/cacme/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php new file mode 100644 index 0000000..51850e1 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.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 Monolog\Processor; + +/** + * Injects url/method and remote IP of the current web request in all records + * + * @author Jordi Boggiano + */ +class WebProcessor implements ProcessorInterface +{ + /** + * @var array|\ArrayAccess + */ + protected $serverData; + + /** + * Default fields + * + * Array is structured as [key in record.extra => key in $serverData] + * + * @var array + */ + protected $extraFields = [ + 'url' => 'REQUEST_URI', + 'ip' => 'REMOTE_ADDR', + 'http_method' => 'REQUEST_METHOD', + 'server' => 'SERVER_NAME', + 'referrer' => 'HTTP_REFERER', + 'user_agent' => 'HTTP_USER_AGENT', + ]; + + /** + * @param array|\ArrayAccess|null $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data + * @param array|array|null $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data + */ + public function __construct($serverData = null, array $extraFields = null) + { + if (null === $serverData) { + $this->serverData = &$_SERVER; + } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { + $this->serverData = $serverData; + } else { + throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); + } + + $defaultEnabled = ['url', 'ip', 'http_method', 'server', 'referrer']; + if (isset($this->serverData['UNIQUE_ID'])) { + $this->extraFields['unique_id'] = 'UNIQUE_ID'; + $defaultEnabled[] = 'unique_id'; + } + + if (null === $extraFields) { + $extraFields = $defaultEnabled; + } + if (isset($extraFields[0])) { + foreach (array_keys($this->extraFields) as $fieldName) { + if (!in_array($fieldName, $extraFields)) { + unset($this->extraFields[$fieldName]); + } + } + } else { + $this->extraFields = $extraFields; + } + } + + /** + * {@inheritDoc} + */ + public function __invoke(array $record): array + { + // skip processing if for some reason request data + // is not present (CLI or wonky SAPIs) + if (!isset($this->serverData['REQUEST_URI'])) { + return $record; + } + + $record['extra'] = $this->appendExtraFields($record['extra']); + + return $record; + } + + public function addExtraField(string $extraName, string $serverName): self + { + $this->extraFields[$extraName] = $serverName; + + return $this; + } + + /** + * @param mixed[] $extra + * @return mixed[] + */ + private function appendExtraFields(array $extra): array + { + foreach ($this->extraFields as $extraName => $serverName) { + $extra[$extraName] = $this->serverData[$serverName] ?? null; + } + + return $extra; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Registry.php b/cacme/vendor/monolog/monolog/src/Monolog/Registry.php new file mode 100644 index 0000000..ae94ae6 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Registry.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 Monolog; + +use InvalidArgumentException; + +/** + * Monolog log registry + * + * Allows to get `Logger` instances in the global scope + * via static method calls on this class. + * + * + * $application = new Monolog\Logger('application'); + * $api = new Monolog\Logger('api'); + * + * Monolog\Registry::addLogger($application); + * Monolog\Registry::addLogger($api); + * + * function testLogger() + * { + * Monolog\Registry::api()->error('Sent to $api Logger instance'); + * Monolog\Registry::application()->error('Sent to $application Logger instance'); + * } + * + * + * @author Tomas Tatarko + */ +class Registry +{ + /** + * List of all loggers in the registry (by named indexes) + * + * @var Logger[] + */ + private static $loggers = []; + + /** + * Adds new logging channel to the registry + * + * @param Logger $logger Instance of the logging channel + * @param string|null $name Name of the logging channel ($logger->getName() by default) + * @param bool $overwrite Overwrite instance in the registry if the given name already exists? + * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists + * @return void + */ + public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false) + { + $name = $name ?: $logger->getName(); + + if (isset(self::$loggers[$name]) && !$overwrite) { + throw new InvalidArgumentException('Logger with the given name already exists'); + } + + self::$loggers[$name] = $logger; + } + + /** + * Checks if such logging channel exists by name or instance + * + * @param string|Logger $logger Name or logger instance + */ + public static function hasLogger($logger): bool + { + if ($logger instanceof Logger) { + $index = array_search($logger, self::$loggers, true); + + return false !== $index; + } + + return isset(self::$loggers[$logger]); + } + + /** + * Removes instance from registry by name or instance + * + * @param string|Logger $logger Name or logger instance + */ + public static function removeLogger($logger): void + { + if ($logger instanceof Logger) { + if (false !== ($idx = array_search($logger, self::$loggers, true))) { + unset(self::$loggers[$idx]); + } + } else { + unset(self::$loggers[$logger]); + } + } + + /** + * Clears the registry + */ + public static function clear(): void + { + self::$loggers = []; + } + + /** + * Gets Logger instance from the registry + * + * @param string $name Name of the requested Logger instance + * @throws \InvalidArgumentException If named Logger instance is not in the registry + */ + public static function getInstance($name): Logger + { + if (!isset(self::$loggers[$name])) { + throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name)); + } + + return self::$loggers[$name]; + } + + /** + * Gets Logger instance from the registry via static method call + * + * @param string $name Name of the requested Logger instance + * @param mixed[] $arguments Arguments passed to static method call + * @throws \InvalidArgumentException If named Logger instance is not in the registry + * @return Logger Requested instance of Logger + */ + public static function __callStatic($name, $arguments) + { + return self::getInstance($name); + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/ResettableInterface.php b/cacme/vendor/monolog/monolog/src/Monolog/ResettableInterface.php new file mode 100644 index 0000000..2c5fd78 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/ResettableInterface.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 Monolog; + +/** + * Handler or Processor implementing this interface will be reset when Logger::reset() is called. + * + * Resetting ends a log cycle gets them back to their initial state. + * + * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal + * state, and getting it back to a state in which it can receive log records again. + * + * This is useful in case you want to avoid logs leaking between two requests or jobs when you + * have a long running process like a worker or an application server serving multiple requests + * in one process. + * + * @author Grégoire Pineau + */ +interface ResettableInterface +{ + /** + * @return void + */ + public function reset(); +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/SignalHandler.php b/cacme/vendor/monolog/monolog/src/Monolog/SignalHandler.php new file mode 100644 index 0000000..d730eea --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/SignalHandler.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 Monolog; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use ReflectionExtension; + +/** + * Monolog POSIX signal handler + * + * @author Robert Gust-Bardon + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + */ +class SignalHandler +{ + /** @var LoggerInterface */ + private $logger; + + /** @var array SIG_DFL, SIG_IGN or previous callable */ + private $previousSignalHandler = []; + /** @var array */ + private $signalLevelMap = []; + /** @var array */ + private $signalRestartSyscalls = []; + + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * @param int|string $level Level or level name + * @param bool $callPrevious + * @param bool $restartSyscalls + * @param bool|null $async + * @return $this + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function registerSignalHandler(int $signo, $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true): self + { + if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) { + return $this; + } + + $level = Logger::toMonologLevel($level); + + if ($callPrevious) { + $handler = pcntl_signal_get_handler($signo); + $this->previousSignalHandler[$signo] = $handler; + } else { + unset($this->previousSignalHandler[$signo]); + } + $this->signalLevelMap[$signo] = $level; + $this->signalRestartSyscalls[$signo] = $restartSyscalls; + + if ($async !== null) { + pcntl_async_signals($async); + } + + pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls); + + return $this; + } + + /** + * @param mixed $siginfo + */ + public function handleSignal(int $signo, $siginfo = null): void + { + static $signals = []; + + if (!$signals && extension_loaded('pcntl')) { + $pcntl = new ReflectionExtension('pcntl'); + // HHVM 3.24.2 returns an empty array. + foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) { + if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) { + $signals[$value] = $name; + } + } + } + + $level = $this->signalLevelMap[$signo] ?? LogLevel::CRITICAL; + $signal = $signals[$signo] ?? $signo; + $context = $siginfo ?? []; + $this->logger->log($level, sprintf('Program received signal %s', $signal), $context); + + if (!isset($this->previousSignalHandler[$signo])) { + return; + } + + if ($this->previousSignalHandler[$signo] === SIG_DFL) { + if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch') + && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill') + ) { + $restartSyscalls = $this->signalRestartSyscalls[$signo] ?? true; + pcntl_signal($signo, SIG_DFL, $restartSyscalls); + pcntl_sigprocmask(SIG_UNBLOCK, [$signo], $oldset); + posix_kill(posix_getpid(), $signo); + pcntl_signal_dispatch(); + pcntl_sigprocmask(SIG_SETMASK, $oldset); + pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls); + } + } elseif (is_callable($this->previousSignalHandler[$signo])) { + $this->previousSignalHandler[$signo]($signo, $siginfo); + } + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Test/TestCase.php b/cacme/vendor/monolog/monolog/src/Monolog/Test/TestCase.php new file mode 100644 index 0000000..bc0b425 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Test/TestCase.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 Monolog\Test; + +use Monolog\Logger; +use Monolog\DateTimeImmutable; +use Monolog\Formatter\FormatterInterface; + +/** + * Lets you easily generate log records and a dummy formatter for testing purposes + * + * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * + * @internal feel free to reuse this to test your own handlers, this is marked internal to avoid issues with PHPStorm https://github.com/Seldaek/monolog/issues/1677 + */ +class TestCase extends \PHPUnit\Framework\TestCase +{ + public function tearDown(): void + { + parent::tearDown(); + + if (isset($this->handler)) { + unset($this->handler); + } + } + + /** + * @param mixed[] $context + * + * @return array Record + * + * @phpstan-param Level $level + * @phpstan-return Record + */ + protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []): array + { + return [ + 'message' => (string) $message, + 'context' => $context, + 'level' => $level, + 'level_name' => Logger::getLevelName($level), + 'channel' => 'test', + 'datetime' => new DateTimeImmutable(true), + 'extra' => [], + ]; + } + + /** + * @phpstan-return Record[] + */ + protected function getMultipleRecords(): array + { + return [ + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + $this->getRecord(Logger::WARNING, 'warning'), + $this->getRecord(Logger::ERROR, 'error'), + ]; + } + + protected function getIdentityFormatter(): FormatterInterface + { + $formatter = $this->createMock(FormatterInterface::class); + $formatter->expects($this->any()) + ->method('format') + ->will($this->returnCallback(function ($record) { + return $record['message']; + })); + + return $formatter; + } +} diff --git a/cacme/vendor/monolog/monolog/src/Monolog/Utils.php b/cacme/vendor/monolog/monolog/src/Monolog/Utils.php new file mode 100644 index 0000000..360c421 --- /dev/null +++ b/cacme/vendor/monolog/monolog/src/Monolog/Utils.php @@ -0,0 +1,284 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +final class Utils +{ + const DEFAULT_JSON_FLAGS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR; + + public static function getClass(object $object): string + { + $class = \get_class($object); + + if (false === ($pos = \strpos($class, "@anonymous\0"))) { + return $class; + } + + if (false === ($parent = \get_parent_class($class))) { + return \substr($class, 0, $pos + 10); + } + + return $parent . '@anonymous'; + } + + public static function substr(string $string, int $start, ?int $length = null): string + { + if (extension_loaded('mbstring')) { + return mb_strcut($string, $start, $length); + } + + return substr($string, $start, (null === $length) ? strlen($string) : $length); + } + + /** + * Makes sure if a relative path is passed in it is turned into an absolute path + * + * @param string $streamUrl stream URL or path without protocol + */ + public static function canonicalizePath(string $streamUrl): string + { + $prefix = ''; + if ('file://' === substr($streamUrl, 0, 7)) { + $streamUrl = substr($streamUrl, 7); + $prefix = 'file://'; + } + + // other type of stream, not supported + if (false !== strpos($streamUrl, '://')) { + return $streamUrl; + } + + // already absolute + if (substr($streamUrl, 0, 1) === '/' || substr($streamUrl, 1, 1) === ':' || substr($streamUrl, 0, 2) === '\\\\') { + return $prefix.$streamUrl; + } + + $streamUrl = getcwd() . '/' . $streamUrl; + + return $prefix.$streamUrl; + } + + /** + * Return the JSON representation of a value + * + * @param mixed $data + * @param int $encodeFlags flags to pass to json encode, defaults to DEFAULT_JSON_FLAGS + * @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null + * @throws \RuntimeException if encoding fails and errors are not ignored + * @return string when errors are ignored and the encoding fails, "null" is returned which is valid json for null + */ + public static function jsonEncode($data, ?int $encodeFlags = null, bool $ignoreErrors = false): string + { + if (null === $encodeFlags) { + $encodeFlags = self::DEFAULT_JSON_FLAGS; + } + + if ($ignoreErrors) { + $json = @json_encode($data, $encodeFlags); + if (false === $json) { + return 'null'; + } + + return $json; + } + + $json = json_encode($data, $encodeFlags); + if (false === $json) { + $json = self::handleJsonError(json_last_error(), $data); + } + + return $json; + } + + /** + * Handle a json_encode failure. + * + * If the failure is due to invalid string encoding, try to clean the + * input and encode again. If the second encoding attempt fails, the + * initial error is not encoding related or the input can't be cleaned then + * raise a descriptive exception. + * + * @param int $code return code of json_last_error function + * @param mixed $data data that was meant to be encoded + * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION + * @throws \RuntimeException if failure can't be corrected + * @return string JSON encoded data after error correction + */ + public static function handleJsonError(int $code, $data, ?int $encodeFlags = null): string + { + if ($code !== JSON_ERROR_UTF8) { + self::throwEncodeError($code, $data); + } + + if (is_string($data)) { + self::detectAndCleanUtf8($data); + } elseif (is_array($data)) { + array_walk_recursive($data, array('Monolog\Utils', 'detectAndCleanUtf8')); + } else { + self::throwEncodeError($code, $data); + } + + if (null === $encodeFlags) { + $encodeFlags = self::DEFAULT_JSON_FLAGS; + } + + $json = json_encode($data, $encodeFlags); + + if ($json === false) { + self::throwEncodeError(json_last_error(), $data); + } + + return $json; + } + + /** + * @internal + */ + public static function pcreLastErrorMessage(int $code): string + { + if (PHP_VERSION_ID >= 80000) { + return preg_last_error_msg(); + } + + $constants = (get_defined_constants(true))['pcre']; + $constants = array_filter($constants, function ($key) { + return substr($key, -6) == '_ERROR'; + }, ARRAY_FILTER_USE_KEY); + + $constants = array_flip($constants); + + return $constants[$code] ?? 'UNDEFINED_ERROR'; + } + + /** + * Throws an exception according to a given code with a customized message + * + * @param int $code return code of json_last_error function + * @param mixed $data data that was meant to be encoded + * @throws \RuntimeException + * + * @return never + */ + private static function throwEncodeError(int $code, $data): void + { + switch ($code) { + case JSON_ERROR_DEPTH: + $msg = 'Maximum stack depth exceeded'; + break; + case JSON_ERROR_STATE_MISMATCH: + $msg = 'Underflow or the modes mismatch'; + break; + case JSON_ERROR_CTRL_CHAR: + $msg = 'Unexpected control character found'; + break; + case JSON_ERROR_UTF8: + $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; + break; + default: + $msg = 'Unknown error'; + } + + throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true)); + } + + /** + * Detect invalid UTF-8 string characters and convert to valid UTF-8. + * + * Valid UTF-8 input will be left unmodified, but strings containing + * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed + * original encoding of ISO-8859-15. This conversion may result in + * incorrect output if the actual encoding was not ISO-8859-15, but it + * will be clean UTF-8 output and will not rely on expensive and fragile + * detection algorithms. + * + * Function converts the input in place in the passed variable so that it + * can be used as a callback for array_walk_recursive. + * + * @param mixed $data Input to check and convert if needed, passed by ref + */ + private static function detectAndCleanUtf8(&$data): void + { + if (is_string($data) && !preg_match('//u', $data)) { + $data = preg_replace_callback( + '/[\x80-\xFF]+/', + function ($m) { + return function_exists('mb_convert_encoding') ? mb_convert_encoding($m[0], 'UTF-8', 'ISO-8859-1') : utf8_encode($m[0]); + }, + $data + ); + if (!is_string($data)) { + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode)); + } + $data = str_replace( + ['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'], + ['€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'], + $data + ); + } + } + + /** + * Converts a string with a valid 'memory_limit' format, to bytes. + * + * @param string|false $val + * @return int|false Returns an integer representing bytes. Returns FALSE in case of error. + */ + public static function expandIniShorthandBytes($val) + { + if (!is_string($val)) { + return false; + } + + // support -1 + if ((int) $val < 0) { + return (int) $val; + } + + if (!preg_match('/^\s*(?\d+)(?:\.\d+)?\s*(?[gmk]?)\s*$/i', $val, $match)) { + return false; + } + + $val = (int) $match['val']; + switch (strtolower($match['unit'] ?? '')) { + case 'g': + $val *= 1024; + case 'm': + $val *= 1024; + case 'k': + $val *= 1024; + } + + return $val; + } + + /** + * @param array $record + */ + public static function getRecordMessageForException(array $record): string + { + $context = ''; + $extra = ''; + try { + if ($record['context']) { + $context = "\nContext: " . json_encode($record['context']); + } + if ($record['extra']) { + $extra = "\nExtra: " . json_encode($record['extra']); + } + } catch (\Throwable $e) { + // noop + } + + return "\nThe exception occurred while attempting to log: " . $record['message'] . $context . $extra; + } +} diff --git a/cacme/vendor/nikic/fast-route/.gitignore b/cacme/vendor/nikic/fast-route/.gitignore new file mode 100644 index 0000000..e378a07 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/.gitignore @@ -0,0 +1,5 @@ +/vendor/ +.idea/ + +# ignore lock file since we have no extra dependencies +composer.lock diff --git a/cacme/vendor/nikic/fast-route/.hhconfig b/cacme/vendor/nikic/fast-route/.hhconfig new file mode 100644 index 0000000..0c2153c --- /dev/null +++ b/cacme/vendor/nikic/fast-route/.hhconfig @@ -0,0 +1 @@ +assume_php=false diff --git a/cacme/vendor/nikic/fast-route/.travis.yml b/cacme/vendor/nikic/fast-route/.travis.yml new file mode 100644 index 0000000..10f8381 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/.travis.yml @@ -0,0 +1,20 @@ +sudo: false +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - hhvm + +script: + - ./vendor/bin/phpunit + +before_install: + - travis_retry composer self-update + +install: + - composer install diff --git a/cacme/vendor/nikic/fast-route/FastRoute.hhi b/cacme/vendor/nikic/fast-route/FastRoute.hhi new file mode 100644 index 0000000..8d50738 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/FastRoute.hhi @@ -0,0 +1,126 @@ +; + } + + class RouteCollector { + public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator); + public function addRoute(mixed $httpMethod, string $route, mixed $handler): void; + public function getData(): array; + } + + class Route { + public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables); + public function matches(string $str): bool; + } + + interface DataGenerator { + public function addRoute(string $httpMethod, array $routeData, mixed $handler); + public function getData(): array; + } + + interface Dispatcher { + const int NOT_FOUND = 0; + const int FOUND = 1; + const int METHOD_NOT_ALLOWED = 2; + public function dispatch(string $httpMethod, string $uri): array; + } + + function simpleDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + ?'routeParser' => classname, + ?'dataGenerator' => classname, + ?'dispatcher' => classname, + ?'routeCollector' => classname, + ) $options = shape()): Dispatcher; + + function cachedDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + ?'routeParser' => classname, + ?'dataGenerator' => classname, + ?'dispatcher' => classname, + ?'routeCollector' => classname, + ?'cacheDisabled' => bool, + ?'cacheFile' => string, + ) $options = shape()): Dispatcher; +} + +namespace FastRoute\DataGenerator { + abstract class RegexBasedAbstract implements \FastRoute\DataGenerator { + protected abstract function getApproxChunkSize(); + protected abstract function processChunk($regexToRoutesMap); + + public function addRoute(string $httpMethod, array $routeData, mixed $handler): void; + public function getData(): array; + } + + class CharCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupPosBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class MarkBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } +} + +namespace FastRoute\Dispatcher { + abstract class RegexBasedAbstract implements \FastRoute\Dispatcher { + protected abstract function dispatchVariableRoute(array $routeData, string $uri): array; + + public function dispatch(string $httpMethod, string $uri): array; + } + + class GroupPosBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class GroupCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class CharCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class MarkBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } +} + +namespace FastRoute\RouteParser { + class Std implements \FastRoute\RouteParser { + const string VARIABLE_REGEX = <<<'REGEX' +\{ + \s* ([a-zA-Z][a-zA-Z0-9_]*) \s* + (?: + : \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*) + )? +\} +REGEX; + const string DEFAULT_DISPATCH_REGEX = '[^/]+'; + public function parse(string $route): array; + } +} diff --git a/cacme/vendor/nikic/fast-route/LICENSE b/cacme/vendor/nikic/fast-route/LICENSE new file mode 100644 index 0000000..478e764 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2013 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. diff --git a/cacme/vendor/nikic/fast-route/README.md b/cacme/vendor/nikic/fast-route/README.md new file mode 100644 index 0000000..91bd466 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/README.md @@ -0,0 +1,313 @@ +FastRoute - Fast request router for PHP +======================================= + +This library provides a fast implementation of a regular expression based router. [Blog post explaining how the +implementation works and why it is fast.][blog_post] + +Install +------- + +To install with composer: + +```sh +composer require nikic/fast-route +``` + +Requires PHP 5.4 or newer. + +Usage +----- + +Here's a basic usage example: + +```php +addRoute('GET', '/users', 'get_all_users_handler'); + // {id} must be a number (\d+) + $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler'); + // The /{title} suffix is optional + $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler'); +}); + +// Fetch method and URI from somewhere +$httpMethod = $_SERVER['REQUEST_METHOD']; +$uri = $_SERVER['REQUEST_URI']; + +// Strip query string (?foo=bar) and decode URI +if (false !== $pos = strpos($uri, '?')) { + $uri = substr($uri, 0, $pos); +} +$uri = rawurldecode($uri); + +$routeInfo = $dispatcher->dispatch($httpMethod, $uri); +switch ($routeInfo[0]) { + case FastRoute\Dispatcher::NOT_FOUND: + // ... 404 Not Found + break; + case FastRoute\Dispatcher::METHOD_NOT_ALLOWED: + $allowedMethods = $routeInfo[1]; + // ... 405 Method Not Allowed + break; + case FastRoute\Dispatcher::FOUND: + $handler = $routeInfo[1]; + $vars = $routeInfo[2]; + // ... call $handler with $vars + break; +} +``` + +### Defining routes + +The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts +a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling +`addRoute()` on the collector instance: + +```php +$r->addRoute($method, $routePattern, $handler); +``` + +The `$method` is an uppercase HTTP method string for which a certain route should match. It +is possible to specify multiple valid methods using an array: + +```php +// These two calls +$r->addRoute('GET', '/test', 'handler'); +$r->addRoute('POST', '/test', 'handler'); +// Are equivalent to this one call +$r->addRoute(['GET', 'POST'], '/test', 'handler'); +``` + +By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo` +and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify +a custom pattern by writing `{bar:[0-9]+}`. Some examples: + +```php +// Matches /user/42, but not /user/xyz +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); + +// Matches /user/foobar, but not /user/foo/bar +$r->addRoute('GET', '/user/{name}', 'handler'); + +// Matches /user/foo/bar as well +$r->addRoute('GET', '/user/{name:.+}', 'handler'); +``` + +Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}` +is not a valid placeholder, because `()` is a capturing group. Instead you can use either +`{lang:en|de}` or `{lang:(?:en|de)}`. + +Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]` +will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position, +not in the middle of a route. + +```php +// This route +$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler'); +// Is equivalent to these two routes +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); +$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler'); + +// Multiple nested optional parts are possible as well +$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler'); + +// This route is NOT valid, because optional parts can only occur at the end +$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler'); +``` + +The `$handler` parameter does not necessarily have to be a callback, it could also be a controller +class name or any other kind of data you wish to associate with the route. FastRoute only tells you +which handler corresponds to your URI, how you interpret it is up to you. + +#### Shorcut methods for common request methods + +For the `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `HEAD` request methods shortcut methods are available. For example: + +```php +$r->get('/get-route', 'get_handler'); +$r->post('/post-route', 'post_handler'); +``` + +Is equivalent to: + +```php +$r->addRoute('GET', '/get-route', 'get_handler'); +$r->addRoute('POST', '/post-route', 'post_handler'); +``` + +#### Route Groups + +Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix. + +For example, defining your routes as: + +```php +$r->addGroup('/admin', function (RouteCollector $r) { + $r->addRoute('GET', '/do-something', 'handler'); + $r->addRoute('GET', '/do-another-thing', 'handler'); + $r->addRoute('GET', '/do-something-else', 'handler'); +}); +``` + +Will have the same result as: + + ```php +$r->addRoute('GET', '/admin/do-something', 'handler'); +$r->addRoute('GET', '/admin/do-another-thing', 'handler'); +$r->addRoute('GET', '/admin/do-something-else', 'handler'); + ``` + +Nested groups are also supported, in which case the prefixes of all the nested groups are combined. + +### Caching + +The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless +caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated +routing data and construct the dispatcher from the cached information: + +```php +addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); +}, [ + 'cacheFile' => __DIR__ . '/route.cache', /* required */ + 'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */ +]); +``` + +The second parameter to the function is an options array, which can be used to specify the cache +file location, among other things. + +### Dispatching a URI + +A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method +accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them +appropriately) is your job - this library is not bound to the PHP web SAPIs. + +The `dispatch()` method returns an array whose first element contains a status code. It is one +of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the +method not allowed status the second array element contains a list of HTTP methods allowed for +the supplied URI. For example: + + [FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']] + +> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the +`Allow:` header to detail available methods for the requested resource. Applications using FastRoute +should use the second array element to add this header when relaying a 405 response. + +For the found status the second array element is the handler that was associated with the route +and the third array element is a dictionary of placeholder names to their values. For example: + + /* Routing against GET /user/nikic/42 */ + + [FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']] + +### Overriding the route parser and dispatcher + +The routing process makes use of three components: A route parser, a data generator and a +dispatcher. The three components adhere to the following interfaces: + +```php + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', +]); +``` + +The above options array corresponds to the defaults. By replacing `GroupCountBased` by +`GroupPosBased` you could switch to a different dispatching strategy. + +### A Note on HEAD Requests + +The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]: + +> The methods GET and HEAD MUST be supported by all general-purpose servers + +To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an +available GET route for a given resource. The PHP web SAPI transparently removes the entity body +from HEAD responses so this behavior has no effect on the vast majority of users. + +However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST +NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is +*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases. + +Finally, note that applications MAY always specify their own HEAD method route for a given +resource to bypass this behavior entirely. + +### Credits + +This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server. + +A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey]. + + +[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1" +[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html +[levi]: https://github.com/morrisonlevi +[rdlowrey]: https://github.com/rdlowrey diff --git a/cacme/vendor/nikic/fast-route/composer.json b/cacme/vendor/nikic/fast-route/composer.json new file mode 100644 index 0000000..fb446a2 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/composer.json @@ -0,0 +1,24 @@ +{ + "name": "nikic/fast-route", + "description": "Fast request router for PHP", + "keywords": ["routing", "router"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": ["src/functions.php"] + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + } +} diff --git a/cacme/vendor/nikic/fast-route/phpunit.xml b/cacme/vendor/nikic/fast-route/phpunit.xml new file mode 100644 index 0000000..3c807b6 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/phpunit.xml @@ -0,0 +1,24 @@ + + + + + + ./test/ + + + + + + ./src/ + + + diff --git a/cacme/vendor/nikic/fast-route/psalm.xml b/cacme/vendor/nikic/fast-route/psalm.xml new file mode 100644 index 0000000..0dca5d7 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/psalm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/cacme/vendor/nikic/fast-route/src/BadRouteException.php b/cacme/vendor/nikic/fast-route/src/BadRouteException.php new file mode 100644 index 0000000..62262ec --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/BadRouteException.php @@ -0,0 +1,7 @@ + $route) { + $suffixLen++; + $suffix .= "\t"; + + $regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})'; + $routeMap[$suffix] = [$route->handler, $route->variables]; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php b/cacme/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php new file mode 100644 index 0000000..54d9a05 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php @@ -0,0 +1,30 @@ + $route) { + $numVariables = count($route->variables); + $numGroups = max($numGroups, $numVariables); + + $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables); + $routeMap[$numGroups + 1] = [$route->handler, $route->variables]; + + ++$numGroups; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php b/cacme/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php new file mode 100644 index 0000000..fc4dc0a --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php @@ -0,0 +1,27 @@ + $route) { + $regexes[] = $regex; + $routeMap[$offset] = [$route->handler, $route->variables]; + + $offset += count($route->variables); + } + + $regex = '~^(?:' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php b/cacme/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php new file mode 100644 index 0000000..0aebed9 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php @@ -0,0 +1,27 @@ + $route) { + $regexes[] = $regex . '(*MARK:' . $markName . ')'; + $routeMap[$markName] = [$route->handler, $route->variables]; + + ++$markName; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php b/cacme/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php new file mode 100644 index 0000000..6457290 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php @@ -0,0 +1,186 @@ +isStaticRoute($routeData)) { + $this->addStaticRoute($httpMethod, $routeData, $handler); + } else { + $this->addVariableRoute($httpMethod, $routeData, $handler); + } + } + + /** + * @return mixed[] + */ + public function getData() + { + if (empty($this->methodToRegexToRoutesMap)) { + return [$this->staticRoutes, []]; + } + + return [$this->staticRoutes, $this->generateVariableRouteData()]; + } + + /** + * @return mixed[] + */ + private function generateVariableRouteData() + { + $data = []; + foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) { + $chunkSize = $this->computeChunkSize(count($regexToRoutesMap)); + $chunks = array_chunk($regexToRoutesMap, $chunkSize, true); + $data[$method] = array_map([$this, 'processChunk'], $chunks); + } + return $data; + } + + /** + * @param int + * @return int + */ + private function computeChunkSize($count) + { + $numParts = max(1, round($count / $this->getApproxChunkSize())); + return (int) ceil($count / $numParts); + } + + /** + * @param mixed[] + * @return bool + */ + private function isStaticRoute($routeData) + { + return count($routeData) === 1 && is_string($routeData[0]); + } + + private function addStaticRoute($httpMethod, $routeData, $handler) + { + $routeStr = $routeData[0]; + + if (isset($this->staticRoutes[$httpMethod][$routeStr])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $routeStr, $httpMethod + )); + } + + if (isset($this->methodToRegexToRoutesMap[$httpMethod])) { + foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) { + if ($route->matches($routeStr)) { + throw new BadRouteException(sprintf( + 'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"', + $routeStr, $route->regex, $httpMethod + )); + } + } + } + + $this->staticRoutes[$httpMethod][$routeStr] = $handler; + } + + private function addVariableRoute($httpMethod, $routeData, $handler) + { + list($regex, $variables) = $this->buildRegexForRoute($routeData); + + if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $regex, $httpMethod + )); + } + + $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route( + $httpMethod, $handler, $regex, $variables + ); + } + + /** + * @param mixed[] + * @return mixed[] + */ + private function buildRegexForRoute($routeData) + { + $regex = ''; + $variables = []; + foreach ($routeData as $part) { + if (is_string($part)) { + $regex .= preg_quote($part, '~'); + continue; + } + + list($varName, $regexPart) = $part; + + if (isset($variables[$varName])) { + throw new BadRouteException(sprintf( + 'Cannot use the same placeholder "%s" twice', $varName + )); + } + + if ($this->regexHasCapturingGroups($regexPart)) { + throw new BadRouteException(sprintf( + 'Regex "%s" for parameter "%s" contains a capturing group', + $regexPart, $varName + )); + } + + $variables[$varName] = $varName; + $regex .= '(' . $regexPart . ')'; + } + + return [$regex, $variables]; + } + + /** + * @param string + * @return bool + */ + private function regexHasCapturingGroups($regex) + { + if (false === strpos($regex, '(')) { + // Needs to have at least a ( to contain a capturing group + return false; + } + + // Semi-accurate detection for capturing groups + return (bool) preg_match( + '~ + (?: + \(\?\( + | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \] + | \\\\ . + ) (*SKIP)(*FAIL) | + \( + (?! + \? (?! <(?![!=]) | P< | \' ) + | \* + ) + ~x', + $regex + ); + } +} diff --git a/cacme/vendor/nikic/fast-route/src/Dispatcher.php b/cacme/vendor/nikic/fast-route/src/Dispatcher.php new file mode 100644 index 0000000..4ae72a3 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Dispatcher.php @@ -0,0 +1,26 @@ + 'value', ...]] + * + * @param string $httpMethod + * @param string $uri + * + * @return array + */ + public function dispatch($httpMethod, $uri); +} diff --git a/cacme/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php b/cacme/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php new file mode 100644 index 0000000..ef1eec1 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php @@ -0,0 +1,31 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][end($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php b/cacme/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php new file mode 100644 index 0000000..493e7a9 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php @@ -0,0 +1,31 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][count($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php b/cacme/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php new file mode 100644 index 0000000..498220e --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php @@ -0,0 +1,33 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + // find first non-empty match + for ($i = 1; '' === $matches[$i]; ++$i); + + list($handler, $varNames) = $data['routeMap'][$i]; + + $vars = []; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[$i++]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php b/cacme/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php new file mode 100644 index 0000000..22eb09b --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php @@ -0,0 +1,31 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) + { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][$matches['MARK']]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php b/cacme/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php new file mode 100644 index 0000000..206e879 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php @@ -0,0 +1,88 @@ +staticRouteMap[$httpMethod][$uri])) { + $handler = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $handler, []]; + } + + $varRouteData = $this->variableRouteData; + if (isset($varRouteData[$httpMethod])) { + $result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + if (isset($this->staticRouteMap['GET'][$uri])) { + $handler = $this->staticRouteMap['GET'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['GET'])) { + $result = $this->dispatchVariableRoute($varRouteData['GET'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + } + + // If nothing else matches, try fallback routes + if (isset($this->staticRouteMap['*'][$uri])) { + $handler = $this->staticRouteMap['*'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['*'])) { + $result = $this->dispatchVariableRoute($varRouteData['*'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // Find allowed methods for this URI by matching against all other HTTP methods as well + $allowedMethods = []; + + foreach ($this->staticRouteMap as $method => $uriMap) { + if ($method !== $httpMethod && isset($uriMap[$uri])) { + $allowedMethods[] = $method; + } + } + + foreach ($varRouteData as $method => $routeData) { + if ($method === $httpMethod) { + continue; + } + + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $allowedMethods[] = $method; + } + } + + // If there are no allowed methods the route simply does not exist + if ($allowedMethods) { + return [self::METHOD_NOT_ALLOWED, $allowedMethods]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/Route.php b/cacme/vendor/nikic/fast-route/src/Route.php new file mode 100644 index 0000000..e1bf7dd --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/Route.php @@ -0,0 +1,47 @@ +httpMethod = $httpMethod; + $this->handler = $handler; + $this->regex = $regex; + $this->variables = $variables; + } + + /** + * Tests whether this route matches the given string. + * + * @param string $str + * + * @return bool + */ + public function matches($str) + { + $regex = '~^' . $this->regex . '$~'; + return (bool) preg_match($regex, $str); + } +} diff --git a/cacme/vendor/nikic/fast-route/src/RouteCollector.php b/cacme/vendor/nikic/fast-route/src/RouteCollector.php new file mode 100644 index 0000000..c1c1762 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/RouteCollector.php @@ -0,0 +1,152 @@ +routeParser = $routeParser; + $this->dataGenerator = $dataGenerator; + $this->currentGroupPrefix = ''; + } + + /** + * Adds a route to the collection. + * + * The syntax used in the $route string depends on the used route parser. + * + * @param string|string[] $httpMethod + * @param string $route + * @param mixed $handler + */ + public function addRoute($httpMethod, $route, $handler) + { + $route = $this->currentGroupPrefix . $route; + $routeDatas = $this->routeParser->parse($route); + foreach ((array) $httpMethod as $method) { + foreach ($routeDatas as $routeData) { + $this->dataGenerator->addRoute($method, $routeData, $handler); + } + } + } + + /** + * Create a route group with a common prefix. + * + * All routes created in the passed callback will have the given group prefix prepended. + * + * @param string $prefix + * @param callable $callback + */ + public function addGroup($prefix, callable $callback) + { + $previousGroupPrefix = $this->currentGroupPrefix; + $this->currentGroupPrefix = $previousGroupPrefix . $prefix; + $callback($this); + $this->currentGroupPrefix = $previousGroupPrefix; + } + + /** + * Adds a GET route to the collection + * + * This is simply an alias of $this->addRoute('GET', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function get($route, $handler) + { + $this->addRoute('GET', $route, $handler); + } + + /** + * Adds a POST route to the collection + * + * This is simply an alias of $this->addRoute('POST', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function post($route, $handler) + { + $this->addRoute('POST', $route, $handler); + } + + /** + * Adds a PUT route to the collection + * + * This is simply an alias of $this->addRoute('PUT', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function put($route, $handler) + { + $this->addRoute('PUT', $route, $handler); + } + + /** + * Adds a DELETE route to the collection + * + * This is simply an alias of $this->addRoute('DELETE', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function delete($route, $handler) + { + $this->addRoute('DELETE', $route, $handler); + } + + /** + * Adds a PATCH route to the collection + * + * This is simply an alias of $this->addRoute('PATCH', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function patch($route, $handler) + { + $this->addRoute('PATCH', $route, $handler); + } + + /** + * Adds a HEAD route to the collection + * + * This is simply an alias of $this->addRoute('HEAD', $route, $handler) + * + * @param string $route + * @param mixed $handler + */ + public function head($route, $handler) + { + $this->addRoute('HEAD', $route, $handler); + } + + /** + * Returns the collected route data, as provided by the data generator. + * + * @return array + */ + public function getData() + { + return $this->dataGenerator->getData(); + } +} diff --git a/cacme/vendor/nikic/fast-route/src/RouteParser.php b/cacme/vendor/nikic/fast-route/src/RouteParser.php new file mode 100644 index 0000000..6a7685c --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/RouteParser.php @@ -0,0 +1,37 @@ + $segment) { + if ($segment === '' && $n !== 0) { + throw new BadRouteException('Empty optional part'); + } + + $currentRoute .= $segment; + $routeDatas[] = $this->parsePlaceholders($currentRoute); + } + return $routeDatas; + } + + /** + * Parses a route string that does not contain optional segments. + * + * @param string + * @return mixed[] + */ + private function parsePlaceholders($route) + { + if (!preg_match_all( + '~' . self::VARIABLE_REGEX . '~x', $route, $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + )) { + return [$route]; + } + + $offset = 0; + $routeData = []; + foreach ($matches as $set) { + if ($set[0][1] > $offset) { + $routeData[] = substr($route, $offset, $set[0][1] - $offset); + } + $routeData[] = [ + $set[1][0], + isset($set[2]) ? trim($set[2][0]) : self::DEFAULT_DISPATCH_REGEX + ]; + $offset = $set[0][1] + strlen($set[0][0]); + } + + if ($offset !== strlen($route)) { + $routeData[] = substr($route, $offset); + } + + return $routeData; + } +} diff --git a/cacme/vendor/nikic/fast-route/src/bootstrap.php b/cacme/vendor/nikic/fast-route/src/bootstrap.php new file mode 100644 index 0000000..0bce3a4 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/src/bootstrap.php @@ -0,0 +1,12 @@ + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + ]; + + /** @var RouteCollector $routeCollector */ + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + return new $options['dispatcher']($routeCollector->getData()); + } + + /** + * @param callable $routeDefinitionCallback + * @param array $options + * + * @return Dispatcher + */ + function cachedDispatcher(callable $routeDefinitionCallback, array $options = []) + { + $options += [ + 'routeParser' => 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + 'cacheDisabled' => false, + ]; + + if (!isset($options['cacheFile'])) { + throw new \LogicException('Must specify "cacheFile" option'); + } + + if (!$options['cacheDisabled'] && file_exists($options['cacheFile'])) { + $dispatchData = require $options['cacheFile']; + if (!is_array($dispatchData)) { + throw new \RuntimeException('Invalid cache file "' . $options['cacheFile'] . '"'); + } + return new $options['dispatcher']($dispatchData); + } + + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + /** @var RouteCollector $routeCollector */ + $dispatchData = $routeCollector->getData(); + if (!$options['cacheDisabled']) { + file_put_contents( + $options['cacheFile'], + ' $this->getDataGeneratorClass(), + 'dispatcher' => $this->getDispatcherClass() + ]; + } + + /** + * @dataProvider provideFoundDispatchCases + */ + public function testFoundDispatches($method, $uri, $callback, $handler, $argDict) + { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $info = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::FOUND, $info[0]); + $this->assertSame($handler, $info[1]); + $this->assertSame($argDict, $info[2]); + } + + /** + * @dataProvider provideNotFoundDispatchCases + */ + public function testNotFoundDispatches($method, $uri, $callback) + { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertArrayNotHasKey(1, $routeInfo, + 'NOT_FOUND result must only contain a single element in the returned info array' + ); + $this->assertSame($dispatcher::NOT_FOUND, $routeInfo[0]); + } + + /** + * @dataProvider provideMethodNotAllowedDispatchCases + */ + public function testMethodNotAllowedDispatches($method, $uri, $callback, $availableMethods) + { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertArrayHasKey(1, $routeInfo, + 'METHOD_NOT_ALLOWED result must return an array of allowed methods at index 1' + ); + + list($routedStatus, $methodArray) = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::METHOD_NOT_ALLOWED, $routedStatus); + $this->assertSame($availableMethods, $methodArray); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot use the same placeholder "test" twice + */ + public function testDuplicateVariableNameError() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/foo/{test}/{test:\d+}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user/([^/]+)" for method "GET" + */ + public function testDuplicateVariableRoute() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/user/{id}', 'handler0'); // oops, forgot \d+ restriction ;) + $r->addRoute('GET', '/user/{name}', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user" for method "GET" + */ + public function testDuplicateStaticRoute() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Static route "/user/nikic" is shadowed by previously defined variable route "/user/([^/]+)" for method "GET" + */ + public function testShadowedStaticRoute() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/nikic', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Regex "(en|de)" for parameter "lang" contains a capturing group + */ + public function testCapturing() + { + \FastRoute\simpleDispatcher(function (RouteCollector $r) { + $r->addRoute('GET', '/{lang:(en|de)}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + public function provideFoundDispatchCases() + { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/resource/123/456'; + $handler = 'handler0'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/handler2'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $handler = 'handler2'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 3 --------------------------------------------------------------------------------------> + + // reuse $callback from #2 + + $method = 'GET'; + $uri = '/user/12345'; + $handler = 'handler1'; + $argDict = ['id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 4 --------------------------------------------------------------------------------------> + + // reuse $callback from #3 + + $method = 'GET'; + $uri = '/user/NaN'; + $handler = 'handler2'; + $argDict = ['name' => 'NaN']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse $callback from #4 + + $method = 'GET'; + $uri = '/user/rdlowrey/12345'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey', 'id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 6 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/12345/extension', 'handler1'); + $r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/user/12345.svg'; + $handler = 'handler2'; + $argDict = ['id' => '12345', 'extension' => 'svg']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 7 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/static0', 'handler2'); + $r->addRoute('GET', '/static1', 'handler3'); + $r->addRoute('HEAD', '/static1', 'handler4'); + }; + + $method = 'HEAD'; + $uri = '/user/rdlowrey'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 8 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #7 + + $method = 'HEAD'; + $uri = '/user/rdlowrey/1234'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey', 'id' => '1234']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 9 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #8 + + $method = 'HEAD'; + $uri = '/static0'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 10 ---- Test existing HEAD route used if available (no fallback) -----------------------> + + // reuse $callback from #9 + + $method = 'HEAD'; + $uri = '/static1'; + $handler = 'handler4'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 11 ---- More specified routes are not shadowed by less specific of another method ------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 12 ---- Handler of more specific routes is used, if it occurs first --------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + $r->addRoute('POST', '/user/{name}', 'handler2'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 13 ---- Route with constant suffix -----------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/edit', 'handler1'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey/edit'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 14 ---- Handle multiple methods with the same handler ----------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $argDict = []; + $cases[] = ['GET', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['POST', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['DELETE', '/user', $callback, 'handlerDelete', $argDict]; + + // 17 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['GET', '/user.json', $callback, 'handler1', ['entity' => 'user']]; + + // 18 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '', 'handler0'); + }; + + $cases[] = ['GET', '', $callback, 'handler0', []]; + + // 19 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('HEAD', '/a/{foo}', 'handler0'); + $r->addRoute('GET', '/b/{foo}', 'handler1'); + }; + + $cases[] = ['HEAD', '/b/bar', $callback, 'handler1', ['foo' => 'bar']]; + + // 20 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('HEAD', '/a', 'handler0'); + $r->addRoute('GET', '/b', 'handler1'); + }; + + $cases[] = ['HEAD', '/b', $callback, 'handler1', []]; + + // 21 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/foo', 'handler0'); + $r->addRoute('HEAD', '/{bar}', 'handler1'); + }; + + $cases[] = ['HEAD', '/foo', $callback, 'handler1', ['bar' => 'foo']]; + + // 22 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('*', '/{user}', 'handler1'); + $r->addRoute('GET', '/user', 'handler2'); + }; + + $cases[] = ['GET', '/user', $callback, 'handler2', []]; + + // 23 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }; + + $cases[] = ['POST', '/user', $callback, 'handler0', []]; + + // 24 ---- + + $cases[] = ['HEAD', '/user', $callback, 'handler1', []]; + + // 25 ---- + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/{bar}', 'handler0'); + $r->addRoute('*', '/foo', 'handler1'); + }; + + $cases[] = ['GET', '/foo', $callback, 'handler0', ['bar' => 'foo']]; + + // 26 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user', 'handler0'); + $r->addRoute('*', '/{foo:.*}', 'handler1'); + }; + + $cases[] = ['POST', '/bar', $callback, 'handler1', ['foo' => 'bar']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideNotFoundDispatchCases() + { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 1 --------------------------------------------------------------------------------------> + + // reuse callback from #0 + $method = 'POST'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 2 --------------------------------------------------------------------------------------> + + // reuse callback from #1 + $method = 'PUT'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse callback from #4 + $method = 'GET'; + $uri = '/user/rdlowrey/12345/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 6 --------------------------------------------------------------------------------------> + + // reuse callback from #5 + $method = 'HEAD'; + + $cases[] = [$method, $uri, $callback]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideMethodNotAllowedDispatchCases() + { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'POST'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + $r->addRoute('POST', '/resource/123/456', 'handler1'); + $r->addRoute('PUT', '/resource/123/456', 'handler2'); + $r->addRoute('*', '/', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET', 'POST', 'PUT']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/user/rdlowrey/42'; + $allowedMethods = ['GET', 'POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute('POST', '/user/{name}', 'handler1'); + $r->addRoute('PUT', '/user/{name:[a-z]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name:[a-z]+}', 'handler3'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $allowedMethods = ['POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function (RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $cases[] = ['PUT', '/user', $callback, ['GET', 'POST', 'DELETE']]; + + // 5 + + $callback = function (RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['PUT', '/user.json', $callback, ['POST', 'GET']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } +} diff --git a/cacme/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php b/cacme/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php new file mode 100644 index 0000000..f821ef5 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php @@ -0,0 +1,16 @@ +markTestSkipped('PHP 5.6 required for MARK support'); + } + } + + protected function getDispatcherClass() + { + return 'FastRoute\\Dispatcher\\MarkBased'; + } + + protected function getDataGeneratorClass() + { + return 'FastRoute\\DataGenerator\\MarkBased'; + } +} diff --git a/cacme/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php b/cacme/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php new file mode 100644 index 0000000..b6fc53f --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php @@ -0,0 +1,44 @@ +markTestSkipped('HHVM only'); + } + if (!version_compare(HHVM_VERSION, '3.9.0', '>=')) { + $this->markTestSkipped('classname requires HHVM 3.9+'); + } + + // The typechecker recurses the whole tree, so it makes sure + // that everything in fixtures/ is valid when this runs. + + $output = []; + $exit_code = null; + exec( + 'hh_server --check ' . escapeshellarg(__DIR__ . '/../../') . ' 2>&1', + $output, + $exit_code + ); + if ($exit_code === self::SERVER_ALREADY_RUNNING_CODE) { + $this->assertTrue( + $recurse, + 'Typechecker still running after running hh_client stop' + ); + // Server already running - 3.10 => 3.11 regression: + // https://github.com/facebook/hhvm/issues/6646 + exec('hh_client stop 2>/dev/null'); + $this->testTypechecks(/* recurse = */ false); + return; + + } + $this->assertSame(0, $exit_code, implode("\n", $output)); + } +} diff --git a/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php b/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php new file mode 100644 index 0000000..05a9af2 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php @@ -0,0 +1,29 @@ + {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + ), + ); +} + +function all_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher( + $collector ==> {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + 'cacheFile' => '/dev/null', + 'cacheDisabled' => false, + ), + ); +} diff --git a/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php b/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php new file mode 100644 index 0000000..61eb541 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php @@ -0,0 +1,11 @@ + {}, shape()); +} + +function empty_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}, shape()); +} diff --git a/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php b/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php new file mode 100644 index 0000000..44b5422 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php @@ -0,0 +1,11 @@ + {}); +} + +function no_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}); +} diff --git a/cacme/vendor/nikic/fast-route/test/RouteCollectorTest.php b/cacme/vendor/nikic/fast-route/test/RouteCollectorTest.php new file mode 100644 index 0000000..cc54407 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/RouteCollectorTest.php @@ -0,0 +1,108 @@ +delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + + $expected = [ + ['DELETE', '/delete', 'delete'], + ['GET', '/get', 'get'], + ['HEAD', '/head', 'head'], + ['PATCH', '/patch', 'patch'], + ['POST', '/post', 'post'], + ['PUT', '/put', 'put'], + ]; + + $this->assertSame($expected, $r->routes); + } + + public function testGroups() + { + $r = new DummyRouteCollector(); + + $r->delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + + $r->addGroup('/group-one', function (DummyRouteCollector $r) { + $r->delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + + $r->addGroup('/group-two', function (DummyRouteCollector $r) { + $r->delete('/delete', 'delete'); + $r->get('/get', 'get'); + $r->head('/head', 'head'); + $r->patch('/patch', 'patch'); + $r->post('/post', 'post'); + $r->put('/put', 'put'); + }); + }); + + $r->addGroup('/admin', function (DummyRouteCollector $r) { + $r->get('-some-info', 'admin-some-info'); + }); + $r->addGroup('/admin-', function (DummyRouteCollector $r) { + $r->get('more-info', 'admin-more-info'); + }); + + $expected = [ + ['DELETE', '/delete', 'delete'], + ['GET', '/get', 'get'], + ['HEAD', '/head', 'head'], + ['PATCH', '/patch', 'patch'], + ['POST', '/post', 'post'], + ['PUT', '/put', 'put'], + ['DELETE', '/group-one/delete', 'delete'], + ['GET', '/group-one/get', 'get'], + ['HEAD', '/group-one/head', 'head'], + ['PATCH', '/group-one/patch', 'patch'], + ['POST', '/group-one/post', 'post'], + ['PUT', '/group-one/put', 'put'], + ['DELETE', '/group-one/group-two/delete', 'delete'], + ['GET', '/group-one/group-two/get', 'get'], + ['HEAD', '/group-one/group-two/head', 'head'], + ['PATCH', '/group-one/group-two/patch', 'patch'], + ['POST', '/group-one/group-two/post', 'post'], + ['PUT', '/group-one/group-two/put', 'put'], + ['GET', '/admin-some-info', 'admin-some-info'], + ['GET', '/admin-more-info', 'admin-more-info'], + ]; + + $this->assertSame($expected, $r->routes); + } +} + +class DummyRouteCollector extends RouteCollector +{ + public $routes = []; + + public function __construct() + { + } + + public function addRoute($method, $route, $handler) + { + $route = $this->currentGroupPrefix . $route; + $this->routes[] = [$method, $route, $handler]; + } +} diff --git a/cacme/vendor/nikic/fast-route/test/RouteParser/StdTest.php b/cacme/vendor/nikic/fast-route/test/RouteParser/StdTest.php new file mode 100644 index 0000000..e13e4de --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/RouteParser/StdTest.php @@ -0,0 +1,154 @@ +parse($routeString); + $this->assertSame($expectedRouteDatas, $routeDatas); + } + + /** @dataProvider provideTestParseError */ + public function testParseError($routeString, $expectedExceptionMessage) + { + $parser = new Std(); + $this->setExpectedException('FastRoute\\BadRouteException', $expectedExceptionMessage); + $parser->parse($routeString); + } + + public function provideTestParse() + { + return [ + [ + '/test', + [ + ['/test'], + ] + ], + [ + '/test/{param}', + [ + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/te{ param }st', + [ + ['/te', ['param', '[^/]+'], 'st'] + ] + ], + [ + '/test/{param1}/test2/{param2}', + [ + ['/test/', ['param1', '[^/]+'], '/test2/', ['param2', '[^/]+']] + ] + ], + [ + '/test/{param:\d+}', + [ + ['/test/', ['param', '\d+']] + ] + ], + [ + '/test/{ param : \d{1,9} }', + [ + ['/test/', ['param', '\d{1,9}']] + ] + ], + [ + '/test[opt]', + [ + ['/test'], + ['/testopt'], + ] + ], + [ + '/test[/{param}]', + [ + ['/test'], + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/{param}[opt]', + [ + ['/', ['param', '[^/]+']], + ['/', ['param', '[^/]+'], 'opt'] + ] + ], + [ + '/test[/{name}[/{id:[0-9]+}]]', + [ + ['/test'], + ['/test/', ['name', '[^/]+']], + ['/test/', ['name', '[^/]+'], '/', ['id', '[0-9]+']], + ] + ], + [ + '', + [ + [''], + ] + ], + [ + '[test]', + [ + [''], + ['test'], + ] + ], + [ + '/{foo-bar}', + [ + ['/', ['foo-bar', '[^/]+']] + ] + ], + [ + '/{_foo:.*}', + [ + ['/', ['_foo', '.*']] + ] + ], + ]; + } + + public function provideTestParseError() + { + return [ + [ + '/test[opt', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[opt[opt2]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/testopt]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[]', + 'Empty optional part' + ], + [ + '/test[[opt]]', + 'Empty optional part' + ], + [ + '[[test]]', + 'Empty optional part' + ], + [ + '/test[/opt]/required', + 'Optional segments can only occur at the end of a route' + ], + ]; + } +} diff --git a/cacme/vendor/nikic/fast-route/test/bootstrap.php b/cacme/vendor/nikic/fast-route/test/bootstrap.php new file mode 100644 index 0000000..3023f41 --- /dev/null +++ b/cacme/vendor/nikic/fast-route/test/bootstrap.php @@ -0,0 +1,11 @@ +clock = $clock; + } + + public function doSomething() + { + /** @var DateTimeImmutable $currentDateAndTime */ + $currentDateAndTime = $this->clock->now(); + // do something useful with that information + } +} +``` + +You can then pick one of the [implementations][implementation-url] of the interface to get a clock. + +If you want to implement the interface, you can require this package and +implement `Psr\Clock\ClockInterface` in your code. + +Don't forget to add `psr/clock-implementation` to your `composer.json`s `provides`-section like this: + +```json +{ + "provides": { + "psr/clock-implementation": "1.0" + } +} +``` + +And please read the [specification text][specification-url] for details on the interface. + +[psr-url]: https://www.php-fig.org/psr/psr-20 +[package-url]: https://packagist.org/packages/psr/clock +[implementation-url]: https://packagist.org/providers/psr/clock-implementation +[specification-url]: https://github.com/php-fig/fig-standards/blob/master/proposed/clock.md diff --git a/cacme/vendor/psr/clock/composer.json b/cacme/vendor/psr/clock/composer.json new file mode 100644 index 0000000..77992ed --- /dev/null +++ b/cacme/vendor/psr/clock/composer.json @@ -0,0 +1,21 @@ +{ + "name": "psr/clock", + "description": "Common interface for reading the clock.", + "keywords": ["psr", "psr-20", "time", "clock", "now"], + "homepage": "https://github.com/php-fig/clock", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": "^7.0 || ^8.0" + }, + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + } +} diff --git a/cacme/vendor/psr/clock/src/ClockInterface.php b/cacme/vendor/psr/clock/src/ClockInterface.php new file mode 100644 index 0000000..7b6d8d8 --- /dev/null +++ b/cacme/vendor/psr/clock/src/ClockInterface.php @@ -0,0 +1,13 @@ +=7.4.0" + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/cacme/vendor/psr/container/src/ContainerExceptionInterface.php b/cacme/vendor/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 0000000..0f213f2 --- /dev/null +++ b/cacme/vendor/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,12 @@ +=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/cacme/vendor/psr/http-factory/src/RequestFactoryInterface.php b/cacme/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 0000000..cb39a08 --- /dev/null +++ b/cacme/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ + `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. +> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. + diff --git a/cacme/vendor/psr/http-message/docs/PSR7-Usage.md b/cacme/vendor/psr/http-message/docs/PSR7-Usage.md new file mode 100644 index 0000000..b6d048a --- /dev/null +++ b/cacme/vendor/psr/http-message/docs/PSR7-Usage.md @@ -0,0 +1,159 @@ +### PSR-7 Usage + +All PSR-7 applications comply with these interfaces +They were created to establish a standard between middleware implementations. + +> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. +> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. + + +The following examples will illustrate how basic operations are done in PSR-7. + +##### Examples + + +For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) +All PSR-7 implementations should have the same behaviour. + +The following will be assumed: +`$request` is an object of `Psr\Http\Message\RequestInterface` and + +`$response` is an object implementing `Psr\Http\Message\RequestInterface` + + +### Working with HTTP Headers + +#### Adding headers to response: + +```php +$response->withHeader('My-Custom-Header', 'My Custom Message'); +``` + +#### Appending values to headers + +```php +$response->withAddedHeader('My-Custom-Header', 'The second message'); +``` + +#### Checking if header exists: + +```php +$request->hasHeader('My-Custom-Header'); // will return false +$response->hasHeader('My-Custom-Header'); // will return true +``` + +> Note: My-Custom-Header was only added in the Response + +#### Getting comma-separated values from a header (also applies to request) + +```php +// getting value from request headers +$request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8" +// getting value from response headers +$response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message" +``` + +#### Getting array of value from a header (also applies to request) +```php +// getting value from request headers +$request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"] +// getting value from response headers +$response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"] +``` + +#### Removing headers from HTTP Messages +```php +// removing a header from Request, removing deprecated "Content-MD5" header +$request->withoutHeader('Content-MD5'); + +// removing a header from Response +// effect: the browser won't know the size of the stream +// the browser will download the stream till it ends +$response->withoutHeader('Content-Length'); +``` + +### Working with HTTP Message Body + +When working with the PSR-7 there are two methods of implementation: +#### 1. Getting the body separately + +> This method makes the body handling easier to understand and is useful when repeatedly calling body methods. (You only call `getBody()` once). Using this method mistakes like `$response->write()` are also prevented. + +```php +$body = $response->getBody(); +// operations on body, eg. read, write, seek +// ... +// replacing the old body +$response->withBody($body); +// this last statement is optional as we working with objects +// in this case the "new" body is same with the "old" one +// the $body variable has the same value as the one in $request, only the reference is passed +``` + +#### 2. Working directly on response + +> This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required + +```php +$response->getBody()->write('hello'); +``` + +### Getting the body contents + +The following snippet gets the contents of a stream contents. +> Note: Streams must be rewinded, if content was written into streams, it will be ignored when calling `getContents()` because the stream pointer is set to the last character, which is `\0` - meaning end of stream. +```php +$body = $response->getBody(); +$body->rewind(); // or $body->seek(0); +$bodyText = $body->getContents(); +``` +> Note: If `$body->seek(1)` is called before `$body->getContents()`, the first character will be ommited as the starting pointer is set to `1`, not `0`. This is why using `$body->rewind()` is recommended. + +### Append to body + +```php +$response->getBody()->write('Hello'); // writing directly +$body = $request->getBody(); // which is a `StreamInterface` +$body->write('xxxxx'); +``` + +### Prepend to body +Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. +The following example will explain the behaviour of streams. + +```php +// assuming our response is initially empty +$body = $repsonse->getBody(); +// writing the string "abcd" +$body->write('abcd'); + +// seeking to start of stream +$body->seek(0); +// writing 'ef' +$body->write('ef'); // at this point the stream contains "efcd" +``` + +#### Prepending by rewriting separately + +```php +// assuming our response body stream only contains: "abcd" +$body = $response->getBody(); +$body->rewind(); +$contents = $body->getContents(); // abcd +// seeking the stream to beginning +$body->rewind(); +$body->write('ef'); // stream contains "efcd" +$body->write($contents); // stream contains "efabcd" +``` + +> Note: `getContents()` seeks the stream while reading it, therefore if the second `rewind()` method call was not present the stream would have resulted in `abcdefabcd` because the `write()` method appends to stream if not preceeded by `rewind()` or `seek(0)`. + +#### Prepending by using contents as a string +```php +$body = $response->getBody(); +$body->rewind(); +$contents = $body->getContents(); // efabcd +$contents = 'ef'.$contents; +$body->rewind(); +$body->write($contents); +``` diff --git a/cacme/vendor/psr/http-message/src/MessageInterface.php b/cacme/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 0000000..8cdb4ed --- /dev/null +++ b/cacme/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,189 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return string[][] Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader(string $name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader(string $name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine(string $name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader(string $name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader(string $name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader(string $name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/cacme/vendor/psr/http-message/src/RequestInterface.php b/cacme/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 0000000..38066df --- /dev/null +++ b/cacme/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,131 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return static + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return static + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return static + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute(string $name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return static + */ + public function withAttribute(string $name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return static + */ + public function withoutAttribute(string $name); +} diff --git a/cacme/vendor/psr/http-message/src/StreamInterface.php b/cacme/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 0000000..5924663 --- /dev/null +++ b/cacme/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,160 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return static A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme(string $scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return static A new instance with the specified user information. + */ + public function withUserInfo(string $user, ?string $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return static A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost(string $host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return static A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort(?int $port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return static A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath(string $path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return static A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery(string $query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return static A new instance with the specified fragment. + */ + public function withFragment(string $fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/cacme/vendor/psr/log/LICENSE b/cacme/vendor/psr/log/LICENSE new file mode 100644 index 0000000..474c952 --- /dev/null +++ b/cacme/vendor/psr/log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cacme/vendor/psr/log/README.md b/cacme/vendor/psr/log/README.md new file mode 100644 index 0000000..a9f20c4 --- /dev/null +++ b/cacme/vendor/psr/log/README.md @@ -0,0 +1,58 @@ +PSR Log +======= + +This repository holds all interfaces/classes/traits related to +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). + +Note that this is not a logger of its own. It is merely an interface that +describes a logger. See the specification for more details. + +Installation +------------ + +```bash +composer require psr/log +``` + +Usage +----- + +If you need a logger, you can use the interface like this: + +```php +logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/cacme/vendor/psr/log/composer.json b/cacme/vendor/psr/log/composer.json new file mode 100644 index 0000000..879fc6f --- /dev/null +++ b/cacme/vendor/psr/log/composer.json @@ -0,0 +1,26 @@ +{ + "name": "psr/log", + "description": "Common interface for logging libraries", + "keywords": ["psr", "psr-3", "log"], + "homepage": "https://github.com/php-fig/log", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=8.0.0" + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + } +} diff --git a/cacme/vendor/psr/log/src/AbstractLogger.php b/cacme/vendor/psr/log/src/AbstractLogger.php new file mode 100644 index 0000000..d60a091 --- /dev/null +++ b/cacme/vendor/psr/log/src/AbstractLogger.php @@ -0,0 +1,15 @@ +logger = $logger; + } +} diff --git a/cacme/vendor/psr/log/src/LoggerInterface.php b/cacme/vendor/psr/log/src/LoggerInterface.php new file mode 100644 index 0000000..b3a24b5 --- /dev/null +++ b/cacme/vendor/psr/log/src/LoggerInterface.php @@ -0,0 +1,125 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function alert(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function critical(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function error(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function warning(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function notice(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function info(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string|\Stringable $message + * @param array $context + * + * @return void + */ + public function debug(string|\Stringable $message, array $context = []): void + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string|\Stringable $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + abstract public function log($level, string|\Stringable $message, array $context = []): void; +} diff --git a/cacme/vendor/psr/log/src/NullLogger.php b/cacme/vendor/psr/log/src/NullLogger.php new file mode 100644 index 0000000..c1cc3c0 --- /dev/null +++ b/cacme/vendor/psr/log/src/NullLogger.php @@ -0,0 +1,30 @@ +logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string|\Stringable $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + public function log($level, string|\Stringable $message, array $context = []): void + { + // noop + } +} diff --git a/cacme/vendor/ralouphie/getallheaders/LICENSE b/cacme/vendor/ralouphie/getallheaders/LICENSE new file mode 100644 index 0000000..be5540c --- /dev/null +++ b/cacme/vendor/ralouphie/getallheaders/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ralph Khattar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/cacme/vendor/ralouphie/getallheaders/README.md b/cacme/vendor/ralouphie/getallheaders/README.md new file mode 100644 index 0000000..9430d76 --- /dev/null +++ b/cacme/vendor/ralouphie/getallheaders/README.md @@ -0,0 +1,27 @@ +getallheaders +============= + +PHP `getallheaders()` polyfill. Compatible with PHP >= 5.3. + +[![Build Status](https://travis-ci.org/ralouphie/getallheaders.svg?branch=master)](https://travis-ci.org/ralouphie/getallheaders) +[![Coverage Status](https://coveralls.io/repos/ralouphie/getallheaders/badge.png?branch=master)](https://coveralls.io/r/ralouphie/getallheaders?branch=master) +[![Latest Stable Version](https://poser.pugx.org/ralouphie/getallheaders/v/stable.png)](https://packagist.org/packages/ralouphie/getallheaders) +[![Latest Unstable Version](https://poser.pugx.org/ralouphie/getallheaders/v/unstable.png)](https://packagist.org/packages/ralouphie/getallheaders) +[![License](https://poser.pugx.org/ralouphie/getallheaders/license.png)](https://packagist.org/packages/ralouphie/getallheaders) + + +This is a simple polyfill for [`getallheaders()`](http://www.php.net/manual/en/function.getallheaders.php). + +## Install + +For PHP version **`>= 5.6`**: + +``` +composer require ralouphie/getallheaders +``` + +For PHP version **`< 5.6`**: + +``` +composer require ralouphie/getallheaders "^2" +``` diff --git a/cacme/vendor/ralouphie/getallheaders/composer.json b/cacme/vendor/ralouphie/getallheaders/composer.json new file mode 100644 index 0000000..de8ce62 --- /dev/null +++ b/cacme/vendor/ralouphie/getallheaders/composer.json @@ -0,0 +1,26 @@ +{ + "name": "ralouphie/getallheaders", + "description": "A polyfill for getallheaders.", + "license": "MIT", + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^5 || ^6.5", + "php-coveralls/php-coveralls": "^2.1" + }, + "autoload": { + "files": ["src/getallheaders.php"] + }, + "autoload-dev": { + "psr-4": { + "getallheaders\\Tests\\": "tests/" + } + } +} diff --git a/cacme/vendor/ralouphie/getallheaders/src/getallheaders.php b/cacme/vendor/ralouphie/getallheaders/src/getallheaders.php new file mode 100644 index 0000000..c7285a5 --- /dev/null +++ b/cacme/vendor/ralouphie/getallheaders/src/getallheaders.php @@ -0,0 +1,46 @@ + 'Content-Type', + 'CONTENT_LENGTH' => 'Content-Length', + 'CONTENT_MD5' => 'Content-Md5', + ); + + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) === 'HTTP_') { + $key = substr($key, 5); + if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) { + $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); + $headers[$key] = $value; + } + } elseif (isset($copy_server[$key])) { + $headers[$copy_server[$key]] = $value; + } + } + + if (!isset($headers['Authorization'])) { + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { + $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + } elseif (isset($_SERVER['PHP_AUTH_USER'])) { + $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; + $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass); + } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { + $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; + } + } + + return $headers; + } + +} diff --git a/cacme/vendor/respect/stringifier/LICENSE.md b/cacme/vendor/respect/stringifier/LICENSE.md new file mode 100644 index 0000000..b7df61c --- /dev/null +++ b/cacme/vendor/respect/stringifier/LICENSE.md @@ -0,0 +1,21 @@ +# License + +Copyright (c) [Henrique Moody](http://github.com/henriquemoody). + +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/cacme/vendor/respect/stringifier/README.md b/cacme/vendor/respect/stringifier/README.md new file mode 100644 index 0000000..c880904 --- /dev/null +++ b/cacme/vendor/respect/stringifier/README.md @@ -0,0 +1,46 @@ +# Respect\Stringifier + +[![Build Status](https://img.shields.io/travis/Respect/Stringifier/master.svg?style=flat-square)](http://travis-ci.org/Respect/Stringifier) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/Respect/Stringifier/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/Respect/Stringifier/?branch=master) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/Respect/Stringifier/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/Respect/Stringifier/?branch=master) +[![Latest Stable Version](https://img.shields.io/packagist/v/respect/stringifier.svg?style=flat-square)](https://packagist.org/packages/respect/stringifier) +[![Total Downloads](https://img.shields.io/packagist/dt/respect/stringifier.svg?style=flat-square)](https://packagist.org/packages/respect/stringifier) +[![License](https://img.shields.io/packagist/l/respect/stringifier.svg?style=flat-square)](https://packagist.org/packages/respect/stringifier) + +Converts any PHP value into a string. + +## Installation + +Package is available on [Packagist](https://packagist.org/packages/respect/stringifier), you can install it +using [Composer](http://getcomposer.org). + +```bash +composer require respect/stringifier +``` + +This library requires PHP >= 7.1. + +## Feature Guide + +Below a quick guide of how to use the library. + +### Namespace import + +Respect\Stringifier is namespaced, and you can make your life easier by importing +a single function into your context: + +```php +use function Respect\Stringifier\stringify; +``` + +Stringifier was built using objects, the `stringify()` is a easy way to use it. + +### Usage + +Simply use the function to convert any value you want to: + +```php +echo stringify($value); +``` + +To see more examples of how to use the library check the [integration tests](tests/integration). diff --git a/cacme/vendor/respect/stringifier/composer.json b/cacme/vendor/respect/stringifier/composer.json new file mode 100644 index 0000000..f63ace2 --- /dev/null +++ b/cacme/vendor/respect/stringifier/composer.json @@ -0,0 +1,36 @@ +{ + "name": "respect/stringifier", + "description": "Converts any value to a string", + "keywords": ["respect", "stringifier", "stringify"], + "type": "library", + "homepage": "http://respect.github.io/Stringifier/", + "license": "MIT", + "authors": [ + { + "name": "Respect/Stringifier Contributors", + "homepage": "https://github.com/Respect/Stringifier/graphs/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.8", + "malukenho/docheader": "^0.1.7", + "phpunit/phpunit": "^6.4" + }, + "autoload": { + "psr-4": { + "Respect\\Stringifier\\": "src/" + }, + "files": [ + "src/stringify.php" + ] + }, + "scripts": { + "docheader": "vendor/bin/docheader check src/ tests/", + "test": "vendor/bin/phpunit", + "test-unit": "vendor/bin/phpunit --testsuite=unit", + "test-integration": "vendor/bin/phpunit --testsuite=integration" + } +} diff --git a/cacme/vendor/respect/stringifier/src/Quoter.php b/cacme/vendor/respect/stringifier/src/Quoter.php new file mode 100644 index 0000000..3d5e9cf --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Quoter.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier; + +interface Quoter +{ + /** + * Should add quotes to the given string. + * + * @param string $string The string to add quotes to + * @param int $depth The current depth + * + * @return string + */ + public function quote(string $string, int $depth): string; +} diff --git a/cacme/vendor/respect/stringifier/src/Quoters/CodeQuoter.php b/cacme/vendor/respect/stringifier/src/Quoters/CodeQuoter.php new file mode 100644 index 0000000..d663ce0 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Quoters/CodeQuoter.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Quoters; + +use Respect\Stringifier\Quoter; + +/** + * Add "`" quotes around a string depending on its level. + * + * @author Henrique Moody + */ +final class CodeQuoter implements Quoter +{ + /** + * {@inheritdoc} + */ + public function quote(string $string, int $depth): string + { + if (0 === $depth) { + return sprintf('`%s`', $string); + } + + return $string; + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifier.php b/cacme/vendor/respect/stringifier/src/Stringifier.php new file mode 100644 index 0000000..b89e56d --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifier.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier; + +interface Stringifier +{ + /** + * Converts the value into string if possible. + * + * @param mixed $raw The raw value to be converted. + * @param int $depth The current depth of the conversion. + * + * @return null|string Returns NULL when the conversion is not possible. + */ + public function stringify($raw, int $depth): ?string; +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/ArrayStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/ArrayStringifier.php new file mode 100644 index 0000000..d7912ad --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/ArrayStringifier.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function array_keys; +use function implode; +use function is_array; +use function is_int; +use function sprintf; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts an array value into a string. + * + * @author Henrique Moody + */ +final class ArrayStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * @var Quoter + */ + private $quoter; + + /** + * @var int + */ + private $maximumDepth; + + /** + * @var int + */ + private $itemsLimit; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + * @param Quoter $quoter + * @param int $maximumDepth + * @param int $itemsLimit + */ + public function __construct(Stringifier $stringifier, Quoter $quoter, int $maximumDepth, int $itemsLimit) + { + $this->stringifier = $stringifier; + $this->quoter = $quoter; + $this->maximumDepth = $maximumDepth; + $this->itemsLimit = $itemsLimit; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_array($raw)) { + return null; + } + + if (empty($raw)) { + return $this->quoter->quote('{ }', $depth); + } + + if ($depth >= $this->maximumDepth) { + return '...'; + } + + $items = []; + $itemsCount = 0; + $isSequential = $this->isSequential($raw); + foreach ($raw as $key => $value) { + if (++$itemsCount > $this->itemsLimit) { + $items[$itemsCount] = '...'; + break; + } + + $items[$itemsCount] = ''; + if (false === $isSequential) { + $items[$itemsCount] .= sprintf('%s: ', $this->stringifier->stringify($key, $depth + 1)); + } + $items[$itemsCount] .= $this->stringifier->stringify($value, $depth + 1); + } + + return $this->quoter->quote(sprintf('{ %s }', implode(', ', $items)), $depth); + } + + /** + * Returns whether the array is sequential or not. + * + * @param array $array + * + * @return bool + */ + private function isSequential(array $array): bool + { + return array_keys($array) === range(0, count($array) - 1); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/BoolStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/BoolStringifier.php new file mode 100644 index 0000000..74debc6 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/BoolStringifier.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function is_bool; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts a boolean value into a string. + * + * @author Henrique Moody + */ +final class BoolStringifier implements Stringifier +{ + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Quoter $quoter + */ + public function __construct(Quoter $quoter) + { + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_bool($raw)) { + return null; + } + + return $this->quoter->quote($raw ? 'TRUE' : 'FALSE', $depth); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/ClusterStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/ClusterStringifier.php new file mode 100644 index 0000000..30de710 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/ClusterStringifier.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use Respect\Stringifier\Quoters\CodeQuoter; +use Respect\Stringifier\Quoters\StringQuoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts a value into a string using the defined Stringifiers. + * + * @author Henrique Moody + */ +final class ClusterStringifier implements Stringifier +{ + /** + * @var Stringifier[] + */ + private $stringifiers; + + /** + * Initializes the stringifier. + * + * @param Stringifier[] ...$stringifiers + */ + public function __construct(Stringifier ...$stringifiers) + { + $this->setStringifiers($stringifiers); + } + + /** + * Create a default instance of the class. + * + * This instance includes all possible stringifiers. + * + * @return ClusterStringifier + */ + public static function createDefault(): self + { + $quoter = new CodeQuoter(); + + $stringifier = new self(); + $stringifier->setStringifiers([ + new TraversableStringifier($stringifier, $quoter), + new DateTimeStringifier($stringifier, $quoter, 'c'), + new ThrowableStringifier($stringifier, $quoter), + new StringableObjectStringifier($stringifier), + new JsonSerializableStringifier($stringifier, $quoter), + new ObjectStringifier($stringifier, $quoter), + new ArrayStringifier($stringifier, $quoter, 3, 5), + new InfiniteStringifier($quoter), + new NanStringifier($quoter), + new ResourceStringifier($quoter), + new BoolStringifier($quoter), + new NullStringifier($quoter), + new JsonParsableStringifier(), + ]); + + return $stringifier; + } + + /** + * Set stringifiers. + * + * @param array $stringifiers + * + * @return void + */ + public function setStringifiers(array $stringifiers): void + { + $this->stringifiers = []; + + foreach ($stringifiers as $stringifier) { + $this->addStringifier($stringifier); + } + } + + /** + * Add a stringifier to the chain + * + * @param Stringifier $stringifier + * + * @return void + */ + public function addStringifier(Stringifier $stringifier): void + { + $this->stringifiers[] = $stringifier; + } + + /** + * {@inheritdoc} + */ + public function stringify($value, int $depth): ?string + { + foreach ($this->stringifiers as $stringifier) { + $string = $stringifier->stringify($value, $depth); + if (null === $string) { + continue; + } + + return $string; + } + + return null; + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/DateTimeStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/DateTimeStringifier.php new file mode 100644 index 0000000..be9335f --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/DateTimeStringifier.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use DateTimeInterface; +use function get_class; +use function sprintf; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts an instance of DateTimeInterface into a string. + * + * @author Henrique Moody + */ +final class DateTimeStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * @var Quoter + */ + private $quoter; + + /** + * @var string + */ + private $format; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + * @param Quoter $quoter + * @param string $format + */ + public function __construct(Stringifier $stringifier, Quoter $quoter, string $format) + { + $this->stringifier = $stringifier; + $this->quoter = $quoter; + $this->format = $format; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!$raw instanceof DateTimeInterface) { + return null; + } + + return $this->quoter->quote( + sprintf( + '[date-time] (%s: %s)', + get_class($raw), + $this->stringifier->stringify($raw->format($this->format), $depth + 1) + ), + $depth + ); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/InfiniteStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/InfiniteStringifier.php new file mode 100644 index 0000000..b09b3d3 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/InfiniteStringifier.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function is_float; +use function is_infinite; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts an infinite float value into a string. + * + * @author Henrique Moody + */ +final class InfiniteStringifier implements Stringifier +{ + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Quoter $quoter + */ + public function __construct(Quoter $quoter) + { + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_float($raw)) { + return null; + } + + if (!is_infinite($raw)) { + return null; + } + + return $this->quoter->quote(($raw > 0 ? '' : '-').'INF', $depth); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/JsonParsableStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/JsonParsableStringifier.php new file mode 100644 index 0000000..3db387b --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/JsonParsableStringifier.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use const JSON_UNESCAPED_UNICODE; +use const JSON_UNESCAPED_SLASHES; +use function json_encode; +use Respect\Stringifier\Stringifier; + +/** + * Converts any value into JSON parsable string representation. + * + * @author Henrique Moody + */ +final class JsonParsableStringifier implements Stringifier +{ + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + $string = json_encode($raw, (JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION)); + if (false === $string) { + return null; + } + + return $string; + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/JsonSerializableStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/JsonSerializableStringifier.php new file mode 100644 index 0000000..67986e5 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/JsonSerializableStringifier.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; +use JsonSerializable; + +/** + * Converts an instance of JsonSerializable into a string. + * + * @author Henrique Moody + */ +final class JsonSerializableStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + * @param Quoter $quoter + */ + public function __construct(Stringifier $stringifier, Quoter $quoter) + { + $this->stringifier = $stringifier; + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!$raw instanceof JsonSerializable) { + return null; + } + + return $this->quoter->quote( + sprintf( + '[json-serializable] (%s: %s)', + get_class($raw), + $this->stringifier->stringify($raw->jsonSerialize(), $depth + 1) + ), + $depth + ); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/NanStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/NanStringifier.php new file mode 100644 index 0000000..5afeefc --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/NanStringifier.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function is_float; +use function is_nan; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts a NaN value into a string. + * + * @author Henrique Moody + */ +final class NanStringifier implements Stringifier +{ + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Quoter $quoter + */ + public function __construct(Quoter $quoter) + { + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_float($raw)) { + return null; + } + + if (!is_nan($raw)) { + return null; + } + + return $this->quoter->quote('NaN', $depth); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/NullStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/NullStringifier.php new file mode 100644 index 0000000..a430e36 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/NullStringifier.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts a NULL value into a string. + * + * @author Henrique Moody + */ +final class NullStringifier implements Stringifier +{ + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Quoter $quoter + */ + public function __construct(Quoter $quoter) + { + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (null !== $raw) { + return null; + } + + return $this->quoter->quote('NULL', $depth); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/ObjectStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/ObjectStringifier.php new file mode 100644 index 0000000..e19cbb3 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/ObjectStringifier.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function get_class; +use function get_object_vars; +use function is_object; +use function sprintf; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts an object into a string. + * + * @author Henrique Moody + */ +final class ObjectStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + * @param Quoter $quoter + */ + public function __construct(Stringifier $stringifier, Quoter $quoter) + { + $this->stringifier = $stringifier; + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_object($raw)) { + return null; + } + + return $this->quoter->quote( + sprintf( + '[object] (%s: %s)', + get_class($raw), + $this->stringifier->stringify(get_object_vars($raw), $depth + 1) + ), + $depth + ); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/ResourceStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/ResourceStringifier.php new file mode 100644 index 0000000..2efb4ea --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/ResourceStringifier.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function get_resource_type; +use function is_resource; +use function sprintf; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; + +/** + * Converts a resource value into a string. + * + * @author Henrique Moody + */ +final class ResourceStringifier implements Stringifier +{ + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Quoter $quoter + */ + public function __construct(Quoter $quoter) + { + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_resource($raw)) { + return null; + } + + return $this->quoter->quote( + sprintf( + '[resource] (%s)', + get_resource_type($raw) + ), + $depth + ); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/StringableObjectStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/StringableObjectStringifier.php new file mode 100644 index 0000000..18e5ef8 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/StringableObjectStringifier.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function is_object; +use function method_exists; +use Respect\Stringifier\Stringifier; + +/** + * Converts a object that implements the __toString() magic method into a string. + * + * @author Henrique Moody + */ +final class StringableObjectStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + */ + public function __construct(Stringifier $stringifier) + { + $this->stringifier = $stringifier; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!is_object($raw)) { + return null; + } + + if (!method_exists($raw, '__toString')) { + return null; + } + + return $this->stringifier->stringify($raw->__toString(), $depth); + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/ThrowableStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/ThrowableStringifier.php new file mode 100644 index 0000000..f9783a3 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/ThrowableStringifier.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function get_class; +use function getcwd; +use function sprintf; +use function str_replace; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; +use Throwable; + +/** + * Converts an instance of Throwable into a string. + * + * @author Henrique Moody + */ +final class ThrowableStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + * @param Quoter $quoter + */ + public function __construct(Stringifier $stringifier, Quoter $quoter) + { + $this->stringifier = $stringifier; + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!$raw instanceof Throwable) { + return null; + } + + return $this->quoter->quote( + sprintf( + '[throwable] (%s: %s)', + get_class($raw), + $this->stringifier->stringify($this->getData($raw), $depth + 1) + ), + $depth + ); + } + + private function getData(Throwable $throwable): array + { + return [ + 'message' => $throwable->getMessage(), + 'code' => $throwable->getCode(), + 'file' => sprintf( + '%s:%d', + str_replace(getcwd().'/', '', $throwable->getFile()), + $throwable->getLine() + ), + ]; + } +} diff --git a/cacme/vendor/respect/stringifier/src/Stringifiers/TraversableStringifier.php b/cacme/vendor/respect/stringifier/src/Stringifiers/TraversableStringifier.php new file mode 100644 index 0000000..6c33f59 --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/Stringifiers/TraversableStringifier.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier\Stringifiers; + +use function get_class; +use function iterator_to_array; +use Respect\Stringifier\Quoter; +use Respect\Stringifier\Stringifier; +use Traversable; + +/** + * Converts an instance of Traversable into a string. + * + * @author Henrique Moody + */ +final class TraversableStringifier implements Stringifier +{ + /** + * @var Stringifier + */ + private $stringifier; + + /** + * @var Quoter + */ + private $quoter; + + /** + * Initializes the stringifier. + * + * @param Stringifier $stringifier + * @param Quoter $quoter + */ + public function __construct(Stringifier $stringifier, Quoter $quoter) + { + $this->stringifier = $stringifier; + $this->quoter = $quoter; + } + + /** + * {@inheritdoc} + */ + public function stringify($raw, int $depth): ?string + { + if (!$raw instanceof Traversable) { + return null; + } + + return $this->quoter->quote( + sprintf( + '[traversable] (%s: %s)', + get_class($raw), + $this->stringifier->stringify(iterator_to_array($raw), $depth + 1) + ), + $depth + ); + } +} diff --git a/cacme/vendor/respect/stringifier/src/stringify.php b/cacme/vendor/respect/stringifier/src/stringify.php new file mode 100644 index 0000000..d12fddf --- /dev/null +++ b/cacme/vendor/respect/stringifier/src/stringify.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Stringifier; + +use Respect\Stringifier\Stringifiers\ClusterStringifier; + +function stringify($value): string +{ + static $stringifier; + + if (null === $stringifier) { + $stringifier = ClusterStringifier::createDefault(); + } + + return $stringifier->stringify($value, 0) ?? '#ERROR#'; +} diff --git a/cacme/vendor/stella-maris/clock/.editorconfig b/cacme/vendor/stella-maris/clock/.editorconfig new file mode 100644 index 0000000..9cf4437 --- /dev/null +++ b/cacme/vendor/stella-maris/clock/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +trim_trailing_whitespace = true +indent_size = tab +indent_style = tab +tab_width = 4 +end_of_line = lf +insert_final_newline = true +max_line_length = off +charset = utf-8 + +[*.{yml,yaml}] +tab_width = 2 + diff --git a/cacme/vendor/stella-maris/clock/LICENSE.md b/cacme/vendor/stella-maris/clock/LICENSE.md new file mode 100644 index 0000000..51aa800 --- /dev/null +++ b/cacme/vendor/stella-maris/clock/LICENSE.md @@ -0,0 +1,9 @@ + + +Copyright Andreas Heigl and ClockInterfaceContributors + +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/cacme/vendor/stella-maris/clock/README.md b/cacme/vendor/stella-maris/clock/README.md new file mode 100644 index 0000000..063e556 --- /dev/null +++ b/cacme/vendor/stella-maris/clock/README.md @@ -0,0 +1,66 @@ +# Clock + +An implementation of the proposed PSR-20 clock-interface + +[![Total Downloads](http://poser.pugx.org/stella-maris/clock/downloads)](https://packagist.org/packages/stella-maris/clock) +[![Latest Stable Version](http://poser.pugx.org/stella-maris/clock/v)](https://packagist.org/packages/stella-maris/clock) +[![Latest Unstable Version](http://poser.pugx.org/stella-maris/clock/v/unstable)](https://packagist.org/packages/stella-maris/clock) + +[![pipeline status](https://gitlab.com/stella-maris/clock/badges/main/pipeline.svg)](https://gitlab.com/stella-maris/clock/-/commits/main) + +## Installation + +```bash +composer require stella-maris/clock +``` + +## Usage + +This interface allows one to inject one of the implemntations that provide the +clock-interface. + +```php +use StellaMaris/Clock/CLockInterface; + +final class PastChecker +{ + public function __construct(private ClockInterface $clock) {} + + public function hasDateTimeAlreadyPassed(DateTimeImmutable $item): bool + { + return $item < $this->clock->now(); + } +} +``` + +## Why + +Within the Framework Interoperability Group (FIG) a working group has started in 2021 to +create a ClockInterface. The works on that have been rather fast and already in the mid of +2021 the interface was more or less finally decided upon. + +### So why this Interface? + +Since mid 2021 no further work has been happening on the Working Group. All requests towards +the editor and the sponsor weren't met with any reaction. + +So after a lot of discussions on the official working group channel I decided to bring this +interface forward by providing the currently agreed upon interface as a separate package +on packagist. + +### But what when the PSR Interface is provided? + +There are two possibilities: +* Either the interface will be provided by the FIG as it is currently, +then this interface will extend the PSR-20 one so that all implementations of this +interface will be immediately PSR20 compatible. +* Or the PSR20 interface will look different: Then all current implementations will +need to provide a spearate implementation for PSR20 compatibility and this interface will +simply coexist with the PSR20 one. + +## Documentation + +For a more thorough information about the interface please check the PSR-20 documentation +at https://github.com/php-fig/fig-standards/blob/master/proposed/clock.md and +https://github.com/php-fig/fig-standards/blob/master/proposed/clock-meta.md + diff --git a/cacme/vendor/stella-maris/clock/composer.json b/cacme/vendor/stella-maris/clock/composer.json new file mode 100644 index 0000000..30a5cba --- /dev/null +++ b/cacme/vendor/stella-maris/clock/composer.json @@ -0,0 +1,27 @@ +{ + "name": "stella-maris/clock", + "description": "A pre-release of the proposed PSR-20 Clock-Interface", + "keywords": [ + "clock", + "psr20", + "datetime", + "point in time" + ], + "homepage": "https://gitlab.com/stella-maris/clock", + "license": "MIT", + "authors": [ + { + "name": "Andreas Heigl", + "role": "Maintainer" + } + ], + "require": { + "php": "^7.0|^8.0", + "psr/clock": "^1.0" + }, + "autoload": { + "psr-4": { + "StellaMaris\\Clock\\": "src" + } + } +} diff --git a/cacme/vendor/stella-maris/clock/src/ClockInterface.php b/cacme/vendor/stella-maris/clock/src/ClockInterface.php new file mode 100644 index 0000000..c310273 --- /dev/null +++ b/cacme/vendor/stella-maris/clock/src/ClockInterface.php @@ -0,0 +1,15 @@ + + * + * Licenses under the MIT-license. For details see the included file LICENSE.md + */ + +namespace StellaMaris\Clock; + +use DateTimeImmutable; +use Psr\Clock\ClockInterface as PsrClockInterface; + +interface ClockInterface extends PsrClockInterface +{ +} diff --git a/cacme/vendor/symfony/console/Application.php b/cacme/vendor/symfony/console/Application.php new file mode 100644 index 0000000..b01efff --- /dev/null +++ b/cacme/vendor/symfony/console/Application.php @@ -0,0 +1,1267 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\CompleteCommand; +use Symfony\Component\Console\Command\DumpCompletionCommand; +use Symfony\Component\Console\Command\HelpCommand; +use Symfony\Component\Console\Command\LazyCommand; +use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\Command\SignalableCommandInterface; +use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleSignalEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Exception\NamespaceNotFoundException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\DebugFormatterHelper; +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Helper\ProcessHelper; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputAwareInterface; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\SignalRegistry\SignalRegistry; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\ErrorHandler\ErrorHandler; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * An Application is the container for a collection of commands. + * + * It is the main entry point of a Console application. + * + * This class is optimized for a standard CLI environment. + * + * Usage: + * + * $app = new Application('myapp', '1.0 (stable)'); + * $app->add(new SimpleCommand()); + * $app->run(); + * + * @author Fabien Potencier + */ +class Application implements ResetInterface +{ + private array $commands = []; + private bool $wantHelps = false; + private $runningCommand = null; + private string $name; + private string $version; + private $commandLoader = null; + private bool $catchExceptions = true; + private bool $autoExit = true; + private $definition; + private $helperSet; + private $dispatcher = null; + private $terminal; + private string $defaultCommand; + private bool $singleCommand = false; + private bool $initialized = false; + private $signalRegistry; + private array $signalsToDispatchEvent = []; + + public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') + { + $this->name = $name; + $this->version = $version; + $this->terminal = new Terminal(); + $this->defaultCommand = 'list'; + if (\defined('SIGINT') && SignalRegistry::isSupported()) { + $this->signalRegistry = new SignalRegistry(); + $this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2]; + } + } + + /** + * @final + */ + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + public function setCommandLoader(CommandLoaderInterface $commandLoader) + { + $this->commandLoader = $commandLoader; + } + + public function getSignalRegistry(): SignalRegistry + { + if (!$this->signalRegistry) { + throw new RuntimeException('Signals are not supported. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); + } + + return $this->signalRegistry; + } + + public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent) + { + $this->signalsToDispatchEvent = $signalsToDispatchEvent; + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + * + * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. + */ + public function run(InputInterface $input = null, OutputInterface $output = null): int + { + if (\function_exists('putenv')) { + @putenv('LINES='.$this->terminal->getHeight()); + @putenv('COLUMNS='.$this->terminal->getWidth()); + } + + if (null === $input) { + $input = new ArgvInput(); + } + + if (null === $output) { + $output = new ConsoleOutput(); + } + + $renderException = function (\Throwable $e) use ($output) { + if ($output instanceof ConsoleOutputInterface) { + $this->renderThrowable($e, $output->getErrorOutput()); + } else { + $this->renderThrowable($e, $output); + } + }; + if ($phpHandler = set_exception_handler($renderException)) { + restore_exception_handler(); + if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { + $errorHandler = true; + } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) { + $phpHandler[0]->setExceptionHandler($errorHandler); + } + } + + $this->configureIO($input, $output); + + try { + $exitCode = $this->doRun($input, $output); + } catch (\Exception $e) { + if (!$this->catchExceptions) { + throw $e; + } + + $renderException($e); + + $exitCode = $e->getCode(); + if (is_numeric($exitCode)) { + $exitCode = (int) $exitCode; + if ($exitCode <= 0) { + $exitCode = 1; + } + } else { + $exitCode = 1; + } + } finally { + // if the exception handler changed, keep it + // otherwise, unregister $renderException + if (!$phpHandler) { + if (set_exception_handler($renderException) === $renderException) { + restore_exception_handler(); + } + restore_exception_handler(); + } elseif (!$errorHandler) { + $finalHandler = $phpHandler[0]->setExceptionHandler(null); + if ($finalHandler !== $renderException) { + $phpHandler[0]->setExceptionHandler($finalHandler); + } + } + } + + if ($this->autoExit) { + if ($exitCode > 255) { + $exitCode = 255; + } + + exit($exitCode); + } + + return $exitCode; + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(['--version', '-V'], true)) { + $output->writeln($this->getLongVersion()); + + return 0; + } + + try { + // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. + $input->bind($this->getDefinition()); + } catch (ExceptionInterface $e) { + // Errors must be ignored, full binding/validation happens later when the command is known. + } + + $name = $this->getCommandName($input); + if (true === $input->hasParameterOption(['--help', '-h'], true)) { + if (!$name) { + $name = 'help'; + $input = new ArrayInput(['command_name' => $this->defaultCommand]); + } else { + $this->wantHelps = true; + } + } + + if (!$name) { + $name = $this->defaultCommand; + $definition = $this->getDefinition(); + $definition->setArguments(array_merge( + $definition->getArguments(), + [ + 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), + ] + )); + } + + try { + $this->runningCommand = null; + // the command name MUST be the first element of the input + $command = $this->find($name); + } catch (\Throwable $e) { + if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + + if (0 === $event->getExitCode()) { + return 0; + } + + $e = $event->getError(); + } + + throw $e; + } + + $alternative = $alternatives[0]; + + $style = new SymfonyStyle($input, $output); + $output->writeln(''); + $formattedBlock = (new FormatterHelper())->formatBlock(sprintf('Command "%s" is not defined.', $name), 'error', true); + $output->writeln($formattedBlock); + if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + + return $event->getExitCode(); + } + + return 1; + } + + $command = $this->find($alternative); + } + + if ($command instanceof LazyCommand) { + $command = $command->getCommand(); + } + + $this->runningCommand = $command; + $exitCode = $this->doRunCommand($command, $input, $output); + $this->runningCommand = null; + + return $exitCode; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + } + + public function setHelperSet(HelperSet $helperSet) + { + $this->helperSet = $helperSet; + } + + /** + * Get the helper set associated with the command. + */ + public function getHelperSet(): HelperSet + { + return $this->helperSet ??= $this->getDefaultHelperSet(); + } + + public function setDefinition(InputDefinition $definition) + { + $this->definition = $definition; + } + + /** + * Gets the InputDefinition related to this Application. + */ + public function getDefinition(): InputDefinition + { + $this->definition ??= $this->getDefaultInputDefinition(); + + if ($this->singleCommand) { + $inputDefinition = $this->definition; + $inputDefinition->setArguments(); + + return $inputDefinition; + } + + return $this->definition; + } + + /** + * Adds suggestions to $suggestions for the current completion input (e.g. option or argument). + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ( + CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() + && 'command' === $input->getCompletionName() + ) { + $commandNames = []; + foreach ($this->all() as $name => $command) { + // skip hidden commands and aliased commands as they already get added below + if ($command->isHidden() || $command->getName() !== $name) { + continue; + } + $commandNames[] = $command->getName(); + foreach ($command->getAliases() as $name) { + $commandNames[] = $name; + } + } + $suggestions->suggestValues(array_filter($commandNames)); + + return; + } + + if (CompletionInput::TYPE_OPTION_NAME === $input->getCompletionType()) { + $suggestions->suggestOptions($this->getDefinition()->getOptions()); + + return; + } + } + + /** + * Gets the help message. + */ + public function getHelp(): string + { + return $this->getLongVersion(); + } + + /** + * Gets whether to catch exceptions or not during commands execution. + */ + public function areExceptionsCaught(): bool + { + return $this->catchExceptions; + } + + /** + * Sets whether to catch exceptions or not during commands execution. + */ + public function setCatchExceptions(bool $boolean) + { + $this->catchExceptions = $boolean; + } + + /** + * Gets whether to automatically exit after a command execution or not. + */ + public function isAutoExitEnabled(): bool + { + return $this->autoExit; + } + + /** + * Sets whether to automatically exit after a command execution or not. + */ + public function setAutoExit(bool $boolean) + { + $this->autoExit = $boolean; + } + + /** + * Gets the name of the application. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Sets the application name. + **/ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * Gets the application version. + */ + public function getVersion(): string + { + return $this->version; + } + + /** + * Sets the application version. + */ + public function setVersion(string $version) + { + $this->version = $version; + } + + /** + * Returns the long version of the application. + * + * @return string + */ + public function getLongVersion() + { + if ('UNKNOWN' !== $this->getName()) { + if ('UNKNOWN' !== $this->getVersion()) { + return sprintf('%s %s', $this->getName(), $this->getVersion()); + } + + return $this->getName(); + } + + return 'Console Tool'; + } + + /** + * Registers a new command. + */ + public function register(string $name): Command + { + return $this->add(new Command($name)); + } + + /** + * Adds an array of command objects. + * + * If a Command is not enabled it will not be added. + * + * @param Command[] $commands An array of commands + */ + public function addCommands(array $commands) + { + foreach ($commands as $command) { + $this->add($command); + } + } + + /** + * Adds a command object. + * + * If a command with the same name already exists, it will be overridden. + * If the command is not enabled it will not be added. + * + * @return Command|null + */ + public function add(Command $command) + { + $this->init(); + + $command->setApplication($this); + + if (!$command->isEnabled()) { + $command->setApplication(null); + + return null; + } + + if (!$command instanceof LazyCommand) { + // Will throw if the command is not correctly initialized. + $command->getDefinition(); + } + + if (!$command->getName()) { + throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command))); + } + + $this->commands[$command->getName()] = $command; + + foreach ($command->getAliases() as $alias) { + $this->commands[$alias] = $command; + } + + return $command; + } + + /** + * Returns a registered command by name or alias. + * + * @return Command + * + * @throws CommandNotFoundException When given command name does not exist + */ + public function get(string $name) + { + $this->init(); + + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + } + + // When the command has a different name than the one used at the command loader level + if (!isset($this->commands[$name])) { + throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); + } + + $command = $this->commands[$name]; + + if ($this->wantHelps) { + $this->wantHelps = false; + + $helpCommand = $this->get('help'); + $helpCommand->setCommand($command); + + return $helpCommand; + } + + return $command; + } + + /** + * Returns true if the command exists, false otherwise. + */ + public function has(string $name): bool + { + $this->init(); + + return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name))); + } + + /** + * Returns an array of all unique namespaces used by currently registered commands. + * + * It does not return the global namespace which always exists. + * + * @return string[] + */ + public function getNamespaces(): array + { + $namespaces = []; + foreach ($this->all() as $command) { + if ($command->isHidden()) { + continue; + } + + $namespaces[] = $this->extractAllNamespaces($command->getName()); + + foreach ($command->getAliases() as $alias) { + $namespaces[] = $this->extractAllNamespaces($alias); + } + } + + return array_values(array_unique(array_filter(array_merge([], ...$namespaces)))); + } + + /** + * Finds a registered namespace by a name or an abbreviation. + * + * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous + */ + public function findNamespace(string $namespace): string + { + $allNamespaces = $this->getNamespaces(); + $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))).'[^:]*'; + $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); + + if (empty($namespaces)) { + $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); + + if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { + if (1 == \count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + + $message .= implode("\n ", $alternatives); + } + + throw new NamespaceNotFoundException($message, $alternatives); + } + + $exact = \in_array($namespace, $namespaces, true); + if (\count($namespaces) > 1 && !$exact) { + throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + } + + return $exact ? $namespace : reset($namespaces); + } + + /** + * Finds a command by name or alias. + * + * Contrary to get, this command tries to find the best + * match if you give it an abbreviation of a name or alias. + * + * @return Command + * + * @throws CommandNotFoundException When command name is incorrect or ambiguous + */ + public function find(string $name) + { + $this->init(); + + $aliases = []; + + foreach ($this->commands as $command) { + foreach ($command->getAliases() as $alias) { + if (!$this->has($alias)) { + $this->commands[$alias] = $command; + } + } + } + + if ($this->has($name)) { + return $this->get($name); + } + + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); + $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))).'[^:]*'; + $commands = preg_grep('{^'.$expr.'}', $allCommands); + + if (empty($commands)) { + $commands = preg_grep('{^'.$expr.'}i', $allCommands); + } + + // if no commands matched or we just matched namespaces + if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { + if (false !== $pos = strrpos($name, ':')) { + // check if a namespace exists and contains commands + $this->findNamespace(substr($name, 0, $pos)); + } + + $message = sprintf('Command "%s" is not defined.', $name); + + if ($alternatives = $this->findAlternatives($name, $allCommands)) { + // remove hidden commands + $alternatives = array_filter($alternatives, function ($name) { + return !$this->get($name)->isHidden(); + }); + + if (1 == \count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + $message .= implode("\n ", $alternatives); + } + + throw new CommandNotFoundException($message, array_values($alternatives)); + } + + // filter out aliases for commands which are already on the list + if (\count($commands) > 1) { + $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) { + if (!$commandList[$nameOrAlias] instanceof Command) { + $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); + } + + $commandName = $commandList[$nameOrAlias]->getName(); + + $aliases[$nameOrAlias] = $commandName; + + return $commandName === $nameOrAlias || !\in_array($commandName, $commands); + })); + } + + if (\count($commands) > 1) { + $usableWidth = $this->terminal->getWidth() - 10; + $abbrevs = array_values($commands); + $maxLen = 0; + foreach ($abbrevs as $abbrev) { + $maxLen = max(Helper::width($abbrev), $maxLen); + } + $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) { + if ($commandList[$cmd]->isHidden()) { + unset($commands[array_search($cmd, $commands)]); + + return false; + } + + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); + + return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; + }, array_values($commands)); + + if (\count($commands) > 1) { + $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); + + throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands)); + } + } + + $command = $this->get(reset($commands)); + + if ($command->isHidden()) { + throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + } + + return $command; + } + + /** + * Gets the commands (registered in the given namespace if provided). + * + * The array keys are the full names and the values the command instances. + * + * @return Command[] + */ + public function all(string $namespace = null) + { + $this->init(); + + if (null === $namespace) { + if (!$this->commandLoader) { + return $this->commands; + } + + $commands = $this->commands; + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + + return $commands; + } + + $commands = []; + foreach ($this->commands as $name => $command) { + if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { + $commands[$name] = $command; + } + } + + if ($this->commandLoader) { + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + } + + return $commands; + } + + /** + * Returns an array of possible abbreviations given a set of names. + * + * @return string[][] + */ + public static function getAbbreviations(array $names): array + { + $abbrevs = []; + foreach ($names as $name) { + for ($len = \strlen($name); $len > 0; --$len) { + $abbrev = substr($name, 0, $len); + $abbrevs[$abbrev][] = $name; + } + } + + return $abbrevs; + } + + public function renderThrowable(\Throwable $e, OutputInterface $output): void + { + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + + $this->doRenderThrowable($e, $output); + + if (null !== $this->runningCommand) { + $output->writeln(sprintf('%s', OutputFormatter::escape(sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } + + protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void + { + do { + $message = trim($e->getMessage()); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $class = get_debug_type($e); + $title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $len = Helper::width($title); + } else { + $len = 0; + } + + if (str_contains($message, "@anonymous\0")) { + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; + }, $message); + } + + $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; + $lines = []; + foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) { + foreach ($this->splitStringByWidth($line, $width - 4) as $line) { + // pre-format lines to get the right string length + $lineLength = Helper::width($line) + 4; + $lines[] = [$line, $lineLength]; + + $len = max($lineLength, $len); + } + } + + $messages = []; + if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + } + $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::width($title)))); + } + foreach ($lines as $line) { + $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); + } + $messages[] = $emptyLine; + $messages[] = ''; + + $output->writeln($messages, OutputInterface::VERBOSITY_QUIET); + + if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $output->writeln('Exception trace:', OutputInterface::VERBOSITY_QUIET); + + // exception related properties + $trace = $e->getTrace(); + + array_unshift($trace, [ + 'function' => '', + 'file' => $e->getFile() ?: 'n/a', + 'line' => $e->getLine() ?: 'n/a', + 'args' => [], + ]); + + for ($i = 0, $count = \count($trace); $i < $count; ++$i) { + $class = $trace[$i]['class'] ?? ''; + $type = $trace[$i]['type'] ?? ''; + $function = $trace[$i]['function'] ?? ''; + $file = $trace[$i]['file'] ?? 'n/a'; + $line = $trace[$i]['line'] ?? 'n/a'; + + $output->writeln(sprintf(' %s%s at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); + } + + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } while ($e = $e->getPrevious()); + } + + /** + * Configures the input and output instances based on the user arguments and options. + */ + protected function configureIO(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(['--ansi'], true)) { + $output->setDecorated(true); + } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) { + $output->setDecorated(false); + } + + if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) { + $input->setInteractive(false); + } + + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: + $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + break; + case 1: + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + break; + case 2: + $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); + break; + case 3: + $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); + break; + default: + $shellVerbosity = 0; + break; + } + + if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $shellVerbosity = -1; + } else { + if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); + $shellVerbosity = 3; + } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); + $shellVerbosity = 2; + } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + $shellVerbosity = 1; + } + } + + if (-1 === $shellVerbosity) { + $input->setInteractive(false); + } + + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY='.$shellVerbosity); + } + $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; + } + + /** + * Runs the current command. + * + * If an event dispatcher has been attached to the application, + * events are also dispatched during the life-cycle of the command. + * + * @return int 0 if everything went fine, or an error code + */ + protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) + { + foreach ($command->getHelperSet() as $helper) { + if ($helper instanceof InputAwareInterface) { + $helper->setInput($input); + } + } + + if ($this->signalsToDispatchEvent) { + $commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : []; + + if ($commandSignals || null !== $this->dispatcher) { + if (!$this->signalRegistry) { + throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); + } + + if (Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); + + foreach ([\SIGINT, \SIGTERM] as $signal) { + $this->signalRegistry->register($signal, static function () use ($sttyMode) { + shell_exec('stty '.$sttyMode); + }); + } + } + } + + if (null !== $this->dispatcher) { + foreach ($this->signalsToDispatchEvent as $signal) { + $event = new ConsoleSignalEvent($command, $input, $output, $signal); + + $this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) { + $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL); + + // No more handlers, we try to simulate PHP default behavior + if (!$hasNext) { + if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) { + exit(0); + } + } + }); + } + } + + foreach ($commandSignals as $signal) { + $this->signalRegistry->register($signal, [$command, 'handleSignal']); + } + } + + if (null === $this->dispatcher) { + return $command->run($input, $output); + } + + // bind before the console.command event, so the listeners have access to input options/arguments + try { + $command->mergeApplicationDefinition(); + $input->bind($command->getDefinition()); + } catch (ExceptionInterface $e) { + // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition + } + + $event = new ConsoleCommandEvent($command, $input, $output); + $e = null; + + try { + $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND); + + if ($event->commandShouldRun()) { + $exitCode = $command->run($input, $output); + } else { + $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; + } + } catch (\Throwable $e) { + $event = new ConsoleErrorEvent($input, $output, $e, $command); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + $e = $event->getError(); + + if (0 === $exitCode = $event->getExitCode()) { + $e = null; + } + } + + $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); + $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE); + + if (null !== $e) { + throw $e; + } + + return $event->getExitCode(); + } + + /** + * Gets the name of the command based on input. + */ + protected function getCommandName(InputInterface $input): ?string + { + return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); + } + + /** + * Gets the default input definition. + */ + protected function getDefaultInputDefinition(): InputDefinition + { + return new InputDefinition([ + new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), + new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the '.$this->defaultCommand.' command'), + new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), + new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), + new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), + new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null), + new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), + ]); + } + + /** + * Gets the default commands that should always be available. + * + * @return Command[] + */ + protected function getDefaultCommands(): array + { + return [new HelpCommand(), new ListCommand(), new CompleteCommand(), new DumpCompletionCommand()]; + } + + /** + * Gets the default helper set with the helpers that should always be available. + */ + protected function getDefaultHelperSet(): HelperSet + { + return new HelperSet([ + new FormatterHelper(), + new DebugFormatterHelper(), + new ProcessHelper(), + new QuestionHelper(), + ]); + } + + /** + * Returns abbreviated suggestions in string format. + */ + private function getAbbreviationSuggestions(array $abbrevs): string + { + return ' '.implode("\n ", $abbrevs); + } + + /** + * Returns the namespace part of the command name. + * + * This method is not part of public API and should not be used directly. + */ + public function extractNamespace(string $name, int $limit = null): string + { + $parts = explode(':', $name, -1); + + return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); + } + + /** + * Finds alternative of $name among $collection, + * if nothing is found in $collection, try in $abbrevs. + * + * @return string[] + */ + private function findAlternatives(string $name, iterable $collection): array + { + $threshold = 1e3; + $alternatives = []; + + $collectionParts = []; + foreach ($collection as $item) { + $collectionParts[$item] = explode(':', $item); + } + + foreach (explode(':', $name) as $i => $subname) { + foreach ($collectionParts as $collectionName => $parts) { + $exists = isset($alternatives[$collectionName]); + if (!isset($parts[$i]) && $exists) { + $alternatives[$collectionName] += $threshold; + continue; + } elseif (!isset($parts[$i])) { + continue; + } + + $lev = levenshtein($subname, $parts[$i]); + if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) { + $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; + } elseif ($exists) { + $alternatives[$collectionName] += $threshold; + } + } + } + + foreach ($collection as $item) { + $lev = levenshtein($name, $item); + if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) { + $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; + } + } + + $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); + ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); + + return array_keys($alternatives); + } + + /** + * Sets the default Command name. + * + * @return $this + */ + public function setDefaultCommand(string $commandName, bool $isSingleCommand = false): static + { + $this->defaultCommand = explode('|', ltrim($commandName, '|'))[0]; + + if ($isSingleCommand) { + // Ensure the command exist + $this->find($commandName); + + $this->singleCommand = true; + } + + return $this; + } + + /** + * @internal + */ + public function isSingleCommand(): bool + { + return $this->singleCommand; + } + + private function splitStringByWidth(string $string, int $width): array + { + // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. + // additionally, array_slice() is not enough as some character has doubled width. + // we need a function to split string not by character count but by string width + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return str_split($string, $width); + } + + $utf8String = mb_convert_encoding($string, 'utf8', $encoding); + $lines = []; + $line = ''; + + $offset = 0; + while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) { + $offset += \strlen($m[0]); + + foreach (preg_split('//u', $m[0]) as $char) { + // test if $char could be appended to current line + if (mb_strwidth($line.$char, 'utf8') <= $width) { + $line .= $char; + continue; + } + // if not, push current line to array and make new line + $lines[] = str_pad($line, $width); + $line = $char; + } + } + + $lines[] = \count($lines) ? str_pad($line, $width) : $line; + + mb_convert_variables($encoding, 'utf8', $lines); + + return $lines; + } + + /** + * Returns all namespaces of the command name. + * + * @return string[] + */ + private function extractAllNamespaces(string $name): array + { + // -1 as third argument is needed to skip the command short name when exploding + $parts = explode(':', $name, -1); + $namespaces = []; + + foreach ($parts as $part) { + if (\count($namespaces)) { + $namespaces[] = end($namespaces).':'.$part; + } else { + $namespaces[] = $part; + } + } + + return $namespaces; + } + + private function init() + { + if ($this->initialized) { + return; + } + $this->initialized = true; + + foreach ($this->getDefaultCommands() as $command) { + $this->add($command); + } + } +} diff --git a/cacme/vendor/symfony/console/Attribute/AsCommand.php b/cacme/vendor/symfony/console/Attribute/AsCommand.php new file mode 100644 index 0000000..b337f54 --- /dev/null +++ b/cacme/vendor/symfony/console/Attribute/AsCommand.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\Console\Attribute; + +/** + * Service tag to autoconfigure commands. + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class AsCommand +{ + public function __construct( + public string $name, + public ?string $description = null, + array $aliases = [], + bool $hidden = false, + ) { + if (!$hidden && !$aliases) { + return; + } + + $name = explode('|', $name); + $name = array_merge($name, $aliases); + + if ($hidden && '' !== $name[0]) { + array_unshift($name, ''); + } + + $this->name = implode('|', $name); + } +} diff --git a/cacme/vendor/symfony/console/CHANGELOG.md b/cacme/vendor/symfony/console/CHANGELOG.md new file mode 100644 index 0000000..9a93c79 --- /dev/null +++ b/cacme/vendor/symfony/console/CHANGELOG.md @@ -0,0 +1,226 @@ +CHANGELOG +========= + +6.0 +--- + + * `Command::setHidden()` has a default value (`true`) for `$hidden` parameter and is final + * Remove `Helper::strlen()`, use `Helper::width()` instead + * Remove `Helper::strlenWithoutDecoration()`, use `Helper::removeDecoration()` instead + * `AddConsoleCommandPass` can not be configured anymore + * Remove `HelperSet::setCommand()` and `getCommand()` without replacement + +5.4 +--- + + * Add `TesterTrait::assertCommandIsSuccessful()` to test command + * Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement + +5.3 +--- + + * Add `GithubActionReporter` to render annotations in a Github Action + * Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options + * Add the `Command::$defaultDescription` static property and the `description` attribute + on the `console.command` tag to allow the `list` command to instantiate commands lazily + * Add option `--short` to the `list` command + * Add support for bright colors + * Add `#[AsCommand]` attribute for declaring commands on PHP 8 + * Add `Helper::width()` and `Helper::length()` + * The `--ansi` and `--no-ansi` options now default to `null`. + +5.2.0 +----- + + * Added `SingleCommandApplication::setAutoExit()` to allow testing via `CommandTester` + * added support for multiline responses to questions through `Question::setMultiline()` + and `Question::isMultiline()` + * Added `SignalRegistry` class to stack signals handlers + * Added support for signals: + * Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods + * Added `SignalableCommandInterface` interface + * Added `TableCellStyle` class to customize table cell + * Removed `php ` prefix invocation from help messages. + +5.1.0 +----- + + * `Command::setHidden()` is final since Symfony 5.1 + * Add `SingleCommandApplication` + * Add `Cursor` class + +5.0.0 +----- + + * removed support for finding hidden commands using an abbreviation, use the full name instead + * removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()` + * removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()` + * removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()` + * removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()` + * removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()` + * removed support for returning `null` from `Command::execute()`, return `0` instead + * `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument + * `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface` + for its `dispatcher` argument + * renamed `Application::renderException()` and `Application::doRenderException()` + to `renderThrowable()` and `doRenderThrowable()` respectively. + +4.4.0 +----- + + * deprecated finding hidden commands using an abbreviation, use the full name instead + * added `Question::setTrimmable` default to true to allow the answer to be trimmed + * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar` + * `Application` implements `ResetInterface` + * marked all dispatched event classes as `@final` + * added support for displaying table horizontally + * deprecated returning `null` from `Command::execute()`, return `0` instead + * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods, + use `renderThrowable()` and `doRenderThrowable()` instead. + * added support for the `NO_COLOR` env var (https://no-color.org/) + +4.3.0 +----- + + * added support for hyperlinks + * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating + * added `Question::setAutocompleterCallback()` to provide a callback function + that dynamically generates suggestions as the user types + +4.2.0 +----- + + * allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to + `ProcessHelper::run()` to pass environment variables + * deprecated passing a command as a string to `ProcessHelper::run()`, + pass it the command as an array of its arguments instead + * made the `ProcessHelper` class final + * added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`) + * added `capture_stderr_separately` option to `CommandTester::execute()` + +4.1.0 +----- + + * added option to run suggested command if command is not found and only 1 alternative is available + * added option to modify console output and print multiple modifiable sections + * added support for iterable messages in output `write` and `writeln` methods + +4.0.0 +----- + + * `OutputFormatter` throws an exception when unknown options are used + * removed `QuestionHelper::setInputStream()/getInputStream()` + * removed `Application::getTerminalWidth()/getTerminalHeight()` and + `Application::setTerminalDimensions()/getTerminalDimensions()` + * removed `ConsoleExceptionEvent` + * removed `ConsoleEvents::EXCEPTION` + +3.4.0 +----- + + * added `SHELL_VERBOSITY` env var to control verbosity + * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 + `ContainerCommandLoader` for commands lazy-loading + * added a case-insensitive command name matching fallback + * added static `Command::$defaultName/getDefaultName()`, allowing for + commands to be registered at compile time in the application command loader. + Setting the `$defaultName` property avoids the need for filling the `command` + attribute on the `console.command` tag when using `AddConsoleCommandPass`. + +3.3.0 +----- + + * added `ExceptionListener` + * added `AddConsoleCommandPass` (originally in FrameworkBundle) + * [BC BREAK] `Input::getOption()` no longer returns the default value for options + with value optional explicitly passed empty + * added console.error event to catch exceptions thrown by other listeners + * deprecated console.exception event in favor of console.error + * added ability to handle `CommandNotFoundException` through the + `console.error` event + * deprecated default validation in `SymfonyQuestionHelper::ask` + +3.2.0 +------ + + * added `setInputs()` method to CommandTester for ease testing of commands expecting inputs + * added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) + * added StreamableInputInterface + * added LockableTrait + +3.1.0 +----- + + * added truncate method to FormatterHelper + * added setColumnWidth(s) method to Table + +2.8.3 +----- + + * remove readline support from the question helper as it caused issues + +2.8.0 +----- + + * use readline for user input in the question helper when available to allow + the use of arrow keys + +2.6.0 +----- + + * added a Process helper + * added a DebugFormatter helper + +2.5.0 +----- + + * deprecated the dialog helper (use the question helper instead) + * deprecated TableHelper in favor of Table + * deprecated ProgressHelper in favor of ProgressBar + * added ConsoleLogger + * added a question helper + * added a way to set the process name of a command + * added a way to set a default command instead of `ListCommand` + +2.4.0 +----- + + * added a way to force terminal dimensions + * added a convenient method to detect verbosity level + * [BC BREAK] made descriptors use output instead of returning a string + +2.3.0 +----- + + * added multiselect support to the select dialog helper + * added Table Helper for tabular data rendering + * added support for events in `Application` + * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()` + * added a way to set the progress bar progress via the `setCurrent` method + * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'` + * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG + +2.2.0 +----- + + * added support for colorization on Windows via ConEmu + * add a method to Dialog Helper to ask for a question and hide the response + * added support for interactive selections in console (DialogHelper::select()) + * added support for autocompletion as you type in Dialog Helper + +2.1.0 +----- + + * added ConsoleOutputInterface + * added the possibility to disable a command (Command::isEnabled()) + * added suggestions when a command does not exist + * added a --raw option to the list command + * added support for STDERR in the console output class (errors are now sent + to STDERR) + * made the defaults (helper set, commands, input definition) in Application + more easily customizable + * added support for the shell even if readline is not available + * added support for process isolation in Symfony shell via + `--process-isolation` switch + * added support for `--`, which disables options parsing after that point + (tokens will be parsed as arguments) diff --git a/cacme/vendor/symfony/console/CI/GithubActionReporter.php b/cacme/vendor/symfony/console/CI/GithubActionReporter.php new file mode 100644 index 0000000..a15c1ff --- /dev/null +++ b/cacme/vendor/symfony/console/CI/GithubActionReporter.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 Symfony\Component\Console\CI; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Utility class for Github actions. + * + * @author Maxime Steinhausser + */ +class GithubActionReporter +{ + private $output; + + /** + * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85 + */ + private const ESCAPED_DATA = [ + '%' => '%25', + "\r" => '%0D', + "\n" => '%0A', + ]; + + /** + * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94 + */ + private const ESCAPED_PROPERTIES = [ + '%' => '%25', + "\r" => '%0D', + "\n" => '%0A', + ':' => '%3A', + ',' => '%2C', + ]; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + } + + public static function isGithubActionEnvironment(): bool + { + return false !== getenv('GITHUB_ACTIONS'); + } + + /** + * Output an error using the Github annotations format. + * + * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + */ + public function error(string $message, string $file = null, int $line = null, int $col = null): void + { + $this->log('error', $message, $file, $line, $col); + } + + /** + * Output a warning using the Github annotations format. + * + * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message + */ + public function warning(string $message, string $file = null, int $line = null, int $col = null): void + { + $this->log('warning', $message, $file, $line, $col); + } + + /** + * Output a debug log using the Github annotations format. + * + * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message + */ + public function debug(string $message, string $file = null, int $line = null, int $col = null): void + { + $this->log('debug', $message, $file, $line, $col); + } + + private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void + { + // Some values must be encoded. + $message = strtr($message, self::ESCAPED_DATA); + + if (!$file) { + // No file provided, output the message solely: + $this->output->writeln(sprintf('::%s::%s', $type, $message)); + + return; + } + + $this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); + } +} diff --git a/cacme/vendor/symfony/console/Color.php b/cacme/vendor/symfony/console/Color.php new file mode 100644 index 0000000..7fcc507 --- /dev/null +++ b/cacme/vendor/symfony/console/Color.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 Symfony\Component\Console; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Fabien Potencier + */ +final class Color +{ + private const COLORS = [ + 'black' => 0, + 'red' => 1, + 'green' => 2, + 'yellow' => 3, + 'blue' => 4, + 'magenta' => 5, + 'cyan' => 6, + 'white' => 7, + 'default' => 9, + ]; + + private const BRIGHT_COLORS = [ + 'gray' => 0, + 'bright-red' => 1, + 'bright-green' => 2, + 'bright-yellow' => 3, + 'bright-blue' => 4, + 'bright-magenta' => 5, + 'bright-cyan' => 6, + 'bright-white' => 7, + ]; + + private const AVAILABLE_OPTIONS = [ + 'bold' => ['set' => 1, 'unset' => 22], + 'underscore' => ['set' => 4, 'unset' => 24], + 'blink' => ['set' => 5, 'unset' => 25], + 'reverse' => ['set' => 7, 'unset' => 27], + 'conceal' => ['set' => 8, 'unset' => 28], + ]; + + private string $foreground; + private string $background; + private array $options = []; + + public function __construct(string $foreground = '', string $background = '', array $options = []) + { + $this->foreground = $this->parseColor($foreground); + $this->background = $this->parseColor($background, true); + + foreach ($options as $option) { + if (!isset(self::AVAILABLE_OPTIONS[$option])) { + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS)))); + } + + $this->options[$option] = self::AVAILABLE_OPTIONS[$option]; + } + } + + public function apply(string $text): string + { + return $this->set().$text.$this->unset(); + } + + public function set(): string + { + $setCodes = []; + if ('' !== $this->foreground) { + $setCodes[] = $this->foreground; + } + if ('' !== $this->background) { + $setCodes[] = $this->background; + } + foreach ($this->options as $option) { + $setCodes[] = $option['set']; + } + if (0 === \count($setCodes)) { + return ''; + } + + return sprintf("\033[%sm", implode(';', $setCodes)); + } + + public function unset(): string + { + $unsetCodes = []; + if ('' !== $this->foreground) { + $unsetCodes[] = 39; + } + if ('' !== $this->background) { + $unsetCodes[] = 49; + } + foreach ($this->options as $option) { + $unsetCodes[] = $option['unset']; + } + if (0 === \count($unsetCodes)) { + return ''; + } + + return sprintf("\033[%sm", implode(';', $unsetCodes)); + } + + private function parseColor(string $color, bool $background = false): string + { + if ('' === $color) { + return ''; + } + + if ('#' === $color[0]) { + $color = substr($color, 1); + + if (3 === \strlen($color)) { + $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2]; + } + + if (6 !== \strlen($color)) { + throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color)); + } + + return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color)); + } + + if (isset(self::COLORS[$color])) { + return ($background ? '4' : '3').self::COLORS[$color]; + } + + if (isset(self::BRIGHT_COLORS[$color])) { + return ($background ? '10' : '9').self::BRIGHT_COLORS[$color]; + } + + throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS))))); + } + + private function convertHexColorToAnsi(int $color): string + { + $r = ($color >> 16) & 255; + $g = ($color >> 8) & 255; + $b = $color & 255; + + // see https://github.com/termstandard/colors/ for more information about true color support + if ('truecolor' !== getenv('COLORTERM')) { + return (string) $this->degradeHexColorToAnsi($r, $g, $b); + } + + return sprintf('8;2;%d;%d;%d', $r, $g, $b); + } + + private function degradeHexColorToAnsi(int $r, int $g, int $b): int + { + if (0 === round($this->getSaturation($r, $g, $b) / 50)) { + return 0; + } + + return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255); + } + + private function getSaturation(int $r, int $g, int $b): int + { + $r = $r / 255; + $g = $g / 255; + $b = $b / 255; + $v = max($r, $g, $b); + + if (0 === $diff = $v - min($r, $g, $b)) { + return 0; + } + + return (int) $diff * 100 / $v; + } +} diff --git a/cacme/vendor/symfony/console/Command/Command.php b/cacme/vendor/symfony/console/Command/Command.php new file mode 100644 index 0000000..986d4bd --- /dev/null +++ b/cacme/vendor/symfony/console/Command/Command.php @@ -0,0 +1,676 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Base class for all commands. + * + * @author Fabien Potencier + */ +class Command +{ + // see https://tldp.org/LDP/abs/html/exitcodes.html + public const SUCCESS = 0; + public const FAILURE = 1; + public const INVALID = 2; + + /** + * @var string|null The default command name + */ + protected static $defaultName; + + /** + * @var string|null The default command description + */ + protected static $defaultDescription; + + private $application = null; + private ?string $name = null; + private ?string $processTitle = null; + private array $aliases = []; + private $definition; + private bool $hidden = false; + private string $help = ''; + private string $description = ''; + private $fullDefinition = null; + private bool $ignoreValidationErrors = false; + private ?\Closure $code = null; + private array $synopsis = []; + private array $usages = []; + private $helperSet = null; + + public static function getDefaultName(): ?string + { + $class = static::class; + + if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { + return $attribute[0]->newInstance()->name; + } + + $r = new \ReflectionProperty($class, 'defaultName'); + + return $class === $r->class ? static::$defaultName : null; + } + + public static function getDefaultDescription(): ?string + { + $class = static::class; + + if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { + return $attribute[0]->newInstance()->description; + } + + $r = new \ReflectionProperty($class, 'defaultDescription'); + + return $class === $r->class ? static::$defaultDescription : null; + } + + /** + * @param string|null $name The name of the command; passing null means it must be set in configure() + * + * @throws LogicException When the command name is empty + */ + public function __construct(string $name = null) + { + $this->definition = new InputDefinition(); + + if (null === $name && null !== $name = static::getDefaultName()) { + $aliases = explode('|', $name); + + if ('' === $name = array_shift($aliases)) { + $this->setHidden(true); + $name = array_shift($aliases); + } + + $this->setAliases($aliases); + } + + if (null !== $name) { + $this->setName($name); + } + + if ('' === $this->description) { + $this->setDescription(static::getDefaultDescription() ?? ''); + } + + $this->configure(); + } + + /** + * Ignores validation errors. + * + * This is mainly useful for the help command. + */ + public function ignoreValidationErrors() + { + $this->ignoreValidationErrors = true; + } + + public function setApplication(Application $application = null) + { + $this->application = $application; + if ($application) { + $this->setHelperSet($application->getHelperSet()); + } else { + $this->helperSet = null; + } + + $this->fullDefinition = null; + } + + public function setHelperSet(HelperSet $helperSet) + { + $this->helperSet = $helperSet; + } + + /** + * Gets the helper set. + */ + public function getHelperSet(): ?HelperSet + { + return $this->helperSet; + } + + /** + * Gets the application instance for this command. + */ + public function getApplication(): ?Application + { + return $this->application; + } + + /** + * Checks whether the command is enabled or not in the current environment. + * + * Override this to check for x or y and return false if the command cannot + * run properly under the current conditions. + * + * @return bool + */ + public function isEnabled() + { + return true; + } + + /** + * Configures the current command. + */ + protected function configure() + { + } + + /** + * Executes the current command. + * + * This method is not abstract because you can use this class + * as a concrete class. In this case, instead of defining the + * execute() method, you set the code to execute by passing + * a Closure to the setCode() method. + * + * @return int 0 if everything went fine, or an exit code + * + * @throws LogicException When this abstract method is not implemented + * + * @see setCode() + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + throw new LogicException('You must override the execute() method in the concrete command class.'); + } + + /** + * Interacts with the user. + * + * This method is executed before the InputDefinition is validated. + * This means that this is the only place where the command can + * interactively ask for values of missing required arguments. + */ + protected function interact(InputInterface $input, OutputInterface $output) + { + } + + /** + * Initializes the command after the input has been bound and before the input + * is validated. + * + * This is mainly useful when a lot of commands extends one main command + * where some things need to be initialized based on the input arguments and options. + * + * @see InputInterface::bind() + * @see InputInterface::validate() + */ + protected function initialize(InputInterface $input, OutputInterface $output) + { + } + + /** + * Runs the command. + * + * The code to execute is either defined directly with the + * setCode() method or by overriding the execute() method + * in a sub-class. + * + * @return int The command exit code + * + * @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}. + * + * @see setCode() + * @see execute() + */ + public function run(InputInterface $input, OutputInterface $output): int + { + // add the application arguments and options + $this->mergeApplicationDefinition(); + + // bind the input against the command specific arguments/options + try { + $input->bind($this->getDefinition()); + } catch (ExceptionInterface $e) { + if (!$this->ignoreValidationErrors) { + throw $e; + } + } + + $this->initialize($input, $output); + + if (null !== $this->processTitle) { + if (\function_exists('cli_set_process_title')) { + if (!@cli_set_process_title($this->processTitle)) { + if ('Darwin' === \PHP_OS) { + $output->writeln('Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.', OutputInterface::VERBOSITY_VERY_VERBOSE); + } else { + cli_set_process_title($this->processTitle); + } + } + } elseif (\function_exists('setproctitle')) { + setproctitle($this->processTitle); + } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { + $output->writeln('Install the proctitle PECL to be able to change the process title.'); + } + } + + if ($input->isInteractive()) { + $this->interact($input, $output); + } + + // The command name argument is often omitted when a command is executed directly with its run() method. + // It would fail the validation if we didn't make sure the command argument is present, + // since it's required by the application. + if ($input->hasArgument('command') && null === $input->getArgument('command')) { + $input->setArgument('command', $this->getName()); + } + + $input->validate(); + + if ($this->code) { + $statusCode = ($this->code)($input, $output); + } else { + $statusCode = $this->execute($input, $output); + + if (!\is_int($statusCode)) { + throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode))); + } + } + + return is_numeric($statusCode) ? (int) $statusCode : 0; + } + + /** + * Adds suggestions to $suggestions for the current completion input (e.g. option or argument). + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + } + + /** + * Sets the code to execute when running this command. + * + * If this method is used, it overrides the code defined + * in the execute() method. + * + * @param callable $code A callable(InputInterface $input, OutputInterface $output) + * + * @return $this + * + * @throws InvalidArgumentException + * + * @see execute() + */ + public function setCode(callable $code): static + { + if ($code instanceof \Closure) { + $r = new \ReflectionFunction($code); + if (null === $r->getClosureThis()) { + set_error_handler(static function () {}); + try { + if ($c = \Closure::bind($code, $this)) { + $code = $c; + } + } finally { + restore_error_handler(); + } + } + } else { + $code = \Closure::fromCallable($code); + } + + $this->code = $code; + + return $this; + } + + /** + * Merges the application definition with the command definition. + * + * This method is not part of public API and should not be used directly. + * + * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments + * + * @internal + */ + public function mergeApplicationDefinition(bool $mergeArgs = true) + { + if (null === $this->application) { + return; + } + + $this->fullDefinition = new InputDefinition(); + $this->fullDefinition->setOptions($this->definition->getOptions()); + $this->fullDefinition->addOptions($this->application->getDefinition()->getOptions()); + + if ($mergeArgs) { + $this->fullDefinition->setArguments($this->application->getDefinition()->getArguments()); + $this->fullDefinition->addArguments($this->definition->getArguments()); + } else { + $this->fullDefinition->setArguments($this->definition->getArguments()); + } + } + + /** + * Sets an array of argument and option instances. + * + * @return $this + */ + public function setDefinition(array|InputDefinition $definition): static + { + if ($definition instanceof InputDefinition) { + $this->definition = $definition; + } else { + $this->definition->setDefinition($definition); + } + + $this->fullDefinition = null; + + return $this; + } + + /** + * Gets the InputDefinition attached to this Command. + */ + public function getDefinition(): InputDefinition + { + return $this->fullDefinition ?? $this->getNativeDefinition(); + } + + /** + * Gets the InputDefinition to be used to create representations of this Command. + * + * Can be overridden to provide the original command representation when it would otherwise + * be changed by merging with the application InputDefinition. + * + * This method is not part of public API and should not be used directly. + */ + public function getNativeDefinition(): InputDefinition + { + return $this->definition ?? throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); + } + + /** + * Adds an argument. + * + * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) + * + * @throws InvalidArgumentException When argument mode is not valid + * + * @return $this + */ + public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null): static + { + $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); + if (null !== $this->fullDefinition) { + $this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default)); + } + + return $this; + } + + /** + * Adds an option. + * + * @param $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param $mode The option mode: One of the InputOption::VALUE_* constants + * @param $default The default value (must be null for InputOption::VALUE_NONE) + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + * + * @return $this + */ + public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null): static + { + $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); + if (null !== $this->fullDefinition) { + $this->fullDefinition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); + } + + return $this; + } + + /** + * Sets the name of the command. + * + * This method can set both the namespace and the name if + * you separate them by a colon (:) + * + * $command->setName('foo:bar'); + * + * @return $this + * + * @throws InvalidArgumentException When the name is invalid + */ + public function setName(string $name): static + { + $this->validateName($name); + + $this->name = $name; + + return $this; + } + + /** + * Sets the process title of the command. + * + * This feature should be used only when creating a long process command, + * like a daemon. + * + * @return $this + */ + public function setProcessTitle(string $title): static + { + $this->processTitle = $title; + + return $this; + } + + /** + * Returns the command name. + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * @param bool $hidden Whether or not the command should be hidden from the list of commands + * + * @return $this + */ + public function setHidden(bool $hidden = true): static + { + $this->hidden = $hidden; + + return $this; + } + + /** + * @return bool whether the command should be publicly shown or not + */ + public function isHidden(): bool + { + return $this->hidden; + } + + /** + * Sets the description for the command. + * + * @return $this + */ + public function setDescription(string $description): static + { + $this->description = $description; + + return $this; + } + + /** + * Returns the description for the command. + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * Sets the help for the command. + * + * @return $this + */ + public function setHelp(string $help): static + { + $this->help = $help; + + return $this; + } + + /** + * Returns the help for the command. + */ + public function getHelp(): string + { + return $this->help; + } + + /** + * Returns the processed help for the command replacing the %command.name% and + * %command.full_name% patterns with the real values dynamically. + */ + public function getProcessedHelp(): string + { + $name = $this->name; + $isSingleCommand = $this->application && $this->application->isSingleCommand(); + + $placeholders = [ + '%command.name%', + '%command.full_name%', + ]; + $replacements = [ + $name, + $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name, + ]; + + return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription()); + } + + /** + * Sets the aliases for the command. + * + * @param string[] $aliases An array of aliases for the command + * + * @return $this + * + * @throws InvalidArgumentException When an alias is invalid + */ + public function setAliases(iterable $aliases): static + { + $list = []; + + foreach ($aliases as $alias) { + $this->validateName($alias); + $list[] = $alias; + } + + $this->aliases = \is_array($aliases) ? $aliases : $list; + + return $this; + } + + /** + * Returns the aliases for the command. + */ + public function getAliases(): array + { + return $this->aliases; + } + + /** + * Returns the synopsis for the command. + * + * @param bool $short Whether to show the short version of the synopsis (with options folded) or not + */ + public function getSynopsis(bool $short = false): string + { + $key = $short ? 'short' : 'long'; + + if (!isset($this->synopsis[$key])) { + $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); + } + + return $this->synopsis[$key]; + } + + /** + * Add a command usage example, it'll be prefixed with the command name. + * + * @return $this + */ + public function addUsage(string $usage): static + { + if (!str_starts_with($usage, $this->name)) { + $usage = sprintf('%s %s', $this->name, $usage); + } + + $this->usages[] = $usage; + + return $this; + } + + /** + * Returns alternative usages of the command. + */ + public function getUsages(): array + { + return $this->usages; + } + + /** + * Gets a helper instance by name. + * + * @throws LogicException if no HelperSet is defined + * @throws InvalidArgumentException if the helper is not defined + */ + public function getHelper(string $name): mixed + { + if (null === $this->helperSet) { + throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); + } + + return $this->helperSet->get($name); + } + + /** + * Validates a command name. + * + * It must be non-empty and parts can optionally be separated by ":". + * + * @throws InvalidArgumentException When the name is invalid + */ + private function validateName(string $name) + { + if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { + throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); + } + } +} diff --git a/cacme/vendor/symfony/console/Command/CompleteCommand.php b/cacme/vendor/symfony/console/Command/CompleteCommand.php new file mode 100644 index 0000000..11ada4e --- /dev/null +++ b/cacme/vendor/symfony/console/Command/CompleteCommand.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 Symfony\Component\Console\Command; + +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Completion\Output\BashCompletionOutput; +use Symfony\Component\Console\Completion\Output\CompletionOutputInterface; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Responsible for providing the values to the shell completion. + * + * @author Wouter de Jong + */ +final class CompleteCommand extends Command +{ + protected static $defaultName = '|_complete'; + protected static $defaultDescription = 'Internal command to provide shell completion suggestions'; + + private $completionOutputs; + + private $isDebug = false; + + /** + * @param array> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value + */ + public function __construct(array $completionOutputs = []) + { + // must be set before the parent constructor, as the property value is used in configure() + $this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class]; + + parent::__construct(); + } + + protected function configure(): void + { + $this + ->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")') + ->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)') + ->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)') + ->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'The version of the completion script') + ; + } + + protected function initialize(InputInterface $input, OutputInterface $output) + { + $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOLEAN); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + try { + // uncomment when a bugfix or BC break has been introduced in the shell completion scripts + // $version = $input->getOption('symfony'); + // if ($version && version_compare($version, 'x.y', '>=')) { + // $message = sprintf('Completion script version is not supported ("%s" given, ">=x.y" required).', $version); + // $this->log($message); + + // $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.'); + + // return 126; + // } + + $shell = $input->getOption('shell'); + if (!$shell) { + throw new \RuntimeException('The "--shell" option must be set.'); + } + + if (!$completionOutput = $this->completionOutputs[$shell] ?? false) { + throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs)))); + } + + $completionInput = $this->createCompletionInput($input); + $suggestions = new CompletionSuggestions(); + + $this->log([ + '', + ''.date('Y-m-d H:i:s').'', + 'Input: ("|" indicates the cursor position)', + ' '.(string) $completionInput, + 'Command:', + ' '.(string) implode(' ', $_SERVER['argv']), + 'Messages:', + ]); + + $command = $this->findCommand($completionInput, $output); + if (null === $command) { + $this->log(' No command found, completing using the Application class.'); + + $this->getApplication()->complete($completionInput, $suggestions); + } elseif ( + $completionInput->mustSuggestArgumentValuesFor('command') + && $command->getName() !== $completionInput->getCompletionValue() + && !\in_array($completionInput->getCompletionValue(), $command->getAliases(), true) + ) { + $this->log(' No command found, completing using the Application class.'); + + // expand shortcut names ("cache:cl") into their full name ("cache:clear") + $suggestions->suggestValues(array_filter(array_merge([$command->getName()], $command->getAliases()))); + } else { + $command->mergeApplicationDefinition(); + $completionInput->bind($command->getDefinition()); + + if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) { + $this->log(' Completing option names for the '.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).' command.'); + + $suggestions->suggestOptions($command->getDefinition()->getOptions()); + } else { + $this->log([ + ' Completing using the '.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).' class.', + ' Completing '.$completionInput->getCompletionType().' for '.$completionInput->getCompletionName().'', + ]); + if (null !== $compval = $completionInput->getCompletionValue()) { + $this->log(' Current value: '.$compval.''); + } + + $command->complete($completionInput, $suggestions); + } + } + + /** @var CompletionOutputInterface $completionOutput */ + $completionOutput = new $completionOutput(); + + $this->log('Suggestions:'); + if ($options = $suggestions->getOptionSuggestions()) { + $this->log(' --'.implode(' --', array_map(function ($o) { return $o->getName(); }, $options))); + } elseif ($values = $suggestions->getValueSuggestions()) { + $this->log(' '.implode(' ', $values)); + } else { + $this->log(' No suggestions were provided'); + } + + $completionOutput->write($suggestions, $output); + } catch (\Throwable $e) { + $this->log([ + 'Error!', + (string) $e, + ]); + + if ($output->isDebug()) { + throw $e; + } + + return self::FAILURE; + } + + return self::SUCCESS; + } + + private function createCompletionInput(InputInterface $input): CompletionInput + { + $currentIndex = $input->getOption('current'); + if (!$currentIndex || !ctype_digit($currentIndex)) { + throw new \RuntimeException('The "--current" option must be set and it must be an integer.'); + } + + $completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex); + + try { + $completionInput->bind($this->getApplication()->getDefinition()); + } catch (ExceptionInterface $e) { + } + + return $completionInput; + } + + private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command + { + try { + $inputName = $completionInput->getFirstArgument(); + if (null === $inputName) { + return null; + } + + return $this->getApplication()->find($inputName); + } catch (CommandNotFoundException $e) { + } + + return null; + } + + private function log($messages): void + { + if (!$this->isDebug) { + return; + } + + $commandName = basename($_SERVER['argv'][0]); + file_put_contents(sys_get_temp_dir().'/sf_'.$commandName.'.log', implode(\PHP_EOL, (array) $messages).\PHP_EOL, \FILE_APPEND); + } +} diff --git a/cacme/vendor/symfony/console/Command/DumpCompletionCommand.php b/cacme/vendor/symfony/console/Command/DumpCompletionCommand.php new file mode 100644 index 0000000..518d606 --- /dev/null +++ b/cacme/vendor/symfony/console/Command/DumpCompletionCommand.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 Symfony\Component\Console\Command; + +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Process; + +/** + * Dumps the completion script for the current shell. + * + * @author Wouter de Jong + */ +final class DumpCompletionCommand extends Command +{ + protected static $defaultName = 'completion'; + protected static $defaultDescription = 'Dump the shell completion script'; + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('shell')) { + $suggestions->suggestValues($this->getSupportedShells()); + } + } + + protected function configure() + { + $fullCommand = $_SERVER['PHP_SELF']; + $commandName = basename($fullCommand); + $fullCommand = @realpath($fullCommand) ?: $fullCommand; + + $this + ->setHelp(<<%command.name% command dumps the shell completion script required +to use shell autocompletion (currently only bash completion is supported). + +Static installation +------------------- + +Dump the script to a global completion file and restart your shell: + + %command.full_name% bash | sudo tee /etc/bash_completion.d/{$commandName} + +Or dump the script to a local file and source it: + + %command.full_name% bash > completion.sh + + # source the file whenever you use the project + source completion.sh + + # or add this line at the end of your "~/.bashrc" file: + source /path/to/completion.sh + +Dynamic installation +-------------------- + +Add this to the end of your shell configuration file (e.g. "~/.bashrc"): + + eval "$({$fullCommand} completion bash)" +EOH + ) + ->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given') + ->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $commandName = basename($_SERVER['argv'][0]); + + if ($input->getOption('debug')) { + $this->tailDebugLog($commandName, $output); + + return self::SUCCESS; + } + + $shell = $input->getArgument('shell') ?? self::guessShell(); + $completionFile = __DIR__.'/../Resources/completion.'.$shell; + if (!file_exists($completionFile)) { + $supportedShells = $this->getSupportedShells(); + + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + if ($shell) { + $output->writeln(sprintf('Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").', $shell, implode('", "', $supportedShells))); + } else { + $output->writeln(sprintf('Shell not detected, Symfony shell completion only supports "%s").', implode('", "', $supportedShells))); + } + + return self::INVALID; + } + + $output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, $this->getApplication()->getVersion()], file_get_contents($completionFile))); + + return self::SUCCESS; + } + + private static function guessShell(): string + { + return basename($_SERVER['SHELL'] ?? ''); + } + + private function tailDebugLog(string $commandName, OutputInterface $output): void + { + $debugFile = sys_get_temp_dir().'/sf_'.$commandName.'.log'; + if (!file_exists($debugFile)) { + touch($debugFile); + } + $process = new Process(['tail', '-f', $debugFile], null, null, null, 0); + $process->run(function (string $type, string $line) use ($output): void { + $output->write($line); + }); + } + + /** + * @return string[] + */ + private function getSupportedShells(): array + { + return array_map(function ($f) { + return pathinfo($f, \PATHINFO_EXTENSION); + }, glob(__DIR__.'/../Resources/completion.*')); + } +} diff --git a/cacme/vendor/symfony/console/Command/HelpCommand.php b/cacme/vendor/symfony/console/Command/HelpCommand.php new file mode 100644 index 0000000..66f8593 --- /dev/null +++ b/cacme/vendor/symfony/console/Command/HelpCommand.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 Symfony\Component\Console\Command; + +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Descriptor\ApplicationDescription; +use Symfony\Component\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * HelpCommand displays the help for a given command. + * + * @author Fabien Potencier + */ +class HelpCommand extends Command +{ + private $command; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->ignoreValidationErrors(); + + $this + ->setName('help') + ->setDefinition([ + new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), + ]) + ->setDescription('Display help for a command') + ->setHelp(<<<'EOF' +The %command.name% command displays help for a given command: + + %command.full_name% list + +You can also output the help in other formats by using the --format option: + + %command.full_name% --format=xml list + +To display the list of available commands, please use the list command. +EOF + ) + ; + } + + public function setCommand(Command $command) + { + $this->command = $command; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->command ??= $this->getApplication()->find($input->getArgument('command_name')); + + $helper = new DescriptorHelper(); + $helper->describe($output, $this->command, [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + ]); + + unset($this->command); + + return 0; + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('command_name')) { + $descriptor = new ApplicationDescription($this->getApplication()); + $suggestions->suggestValues(array_keys($descriptor->getCommands())); + + return; + } + + if ($input->mustSuggestOptionValuesFor('format')) { + $helper = new DescriptorHelper(); + $suggestions->suggestValues($helper->getFormats()); + } + } +} diff --git a/cacme/vendor/symfony/console/Command/LazyCommand.php b/cacme/vendor/symfony/console/Command/LazyCommand.php new file mode 100644 index 0000000..aec4126 --- /dev/null +++ b/cacme/vendor/symfony/console/Command/LazyCommand.php @@ -0,0 +1,194 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Nicolas Grekas + */ +final class LazyCommand extends Command +{ + private $command; + private ?bool $isEnabled; + + public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true) + { + $this->setName($name) + ->setAliases($aliases) + ->setHidden($isHidden) + ->setDescription($description); + + $this->command = $commandFactory; + $this->isEnabled = $isEnabled; + } + + public function ignoreValidationErrors(): void + { + $this->getCommand()->ignoreValidationErrors(); + } + + public function setApplication(Application $application = null): void + { + if ($this->command instanceof parent) { + $this->command->setApplication($application); + } + + parent::setApplication($application); + } + + public function setHelperSet(HelperSet $helperSet): void + { + if ($this->command instanceof parent) { + $this->command->setHelperSet($helperSet); + } + + parent::setHelperSet($helperSet); + } + + public function isEnabled(): bool + { + return $this->isEnabled ?? $this->getCommand()->isEnabled(); + } + + public function run(InputInterface $input, OutputInterface $output): int + { + return $this->getCommand()->run($input, $output); + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + $this->getCommand()->complete($input, $suggestions); + } + + public function setCode(callable $code): static + { + $this->getCommand()->setCode($code); + + return $this; + } + + /** + * @internal + */ + public function mergeApplicationDefinition(bool $mergeArgs = true): void + { + $this->getCommand()->mergeApplicationDefinition($mergeArgs); + } + + public function setDefinition(array|InputDefinition $definition): static + { + $this->getCommand()->setDefinition($definition); + + return $this; + } + + public function getDefinition(): InputDefinition + { + return $this->getCommand()->getDefinition(); + } + + public function getNativeDefinition(): InputDefinition + { + return $this->getCommand()->getNativeDefinition(); + } + + public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null): static + { + $this->getCommand()->addArgument($name, $mode, $description, $default); + + return $this; + } + + public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null): static + { + $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default); + + return $this; + } + + public function setProcessTitle(string $title): static + { + $this->getCommand()->setProcessTitle($title); + + return $this; + } + + public function setHelp(string $help): static + { + $this->getCommand()->setHelp($help); + + return $this; + } + + public function getHelp(): string + { + return $this->getCommand()->getHelp(); + } + + public function getProcessedHelp(): string + { + return $this->getCommand()->getProcessedHelp(); + } + + public function getSynopsis(bool $short = false): string + { + return $this->getCommand()->getSynopsis($short); + } + + public function addUsage(string $usage): static + { + $this->getCommand()->addUsage($usage); + + return $this; + } + + public function getUsages(): array + { + return $this->getCommand()->getUsages(); + } + + public function getHelper(string $name): mixed + { + return $this->getCommand()->getHelper($name); + } + + public function getCommand(): parent + { + if (!$this->command instanceof \Closure) { + return $this->command; + } + + $command = $this->command = ($this->command)(); + $command->setApplication($this->getApplication()); + + if (null !== $this->getHelperSet()) { + $command->setHelperSet($this->getHelperSet()); + } + + $command->setName($this->getName()) + ->setAliases($this->getAliases()) + ->setHidden($this->isHidden()) + ->setDescription($this->getDescription()); + + // Will throw if the command is not correctly initialized. + $command->getDefinition(); + + return $command; + } +} diff --git a/cacme/vendor/symfony/console/Command/ListCommand.php b/cacme/vendor/symfony/console/Command/ListCommand.php new file mode 100644 index 0000000..5c7260f --- /dev/null +++ b/cacme/vendor/symfony/console/Command/ListCommand.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\Console\Command; + +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Descriptor\ApplicationDescription; +use Symfony\Component\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * ListCommand displays the list of all available commands for the application. + * + * @author Fabien Potencier + */ +class ListCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('list') + ->setDefinition([ + new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments'), + ]) + ->setDescription('List commands') + ->setHelp(<<<'EOF' +The %command.name% command lists all commands: + + %command.full_name% + +You can also display the commands for a specific namespace: + + %command.full_name% test + +You can also output the information in other formats by using the --format option: + + %command.full_name% --format=xml + +It's also possible to get raw list of commands (useful for embedding command runner): + + %command.full_name% --raw +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $helper = new DescriptorHelper(); + $helper->describe($output, $this->getApplication(), [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + 'namespace' => $input->getArgument('namespace'), + 'short' => $input->getOption('short'), + ]); + + return 0; + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('namespace')) { + $descriptor = new ApplicationDescription($this->getApplication()); + $suggestions->suggestValues(array_keys($descriptor->getNamespaces())); + + return; + } + + if ($input->mustSuggestOptionValuesFor('format')) { + $helper = new DescriptorHelper(); + $suggestions->suggestValues($helper->getFormats()); + } + } +} diff --git a/cacme/vendor/symfony/console/Command/LockableTrait.php b/cacme/vendor/symfony/console/Command/LockableTrait.php new file mode 100644 index 0000000..7969551 --- /dev/null +++ b/cacme/vendor/symfony/console/Command/LockableTrait.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\Console\Command; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; + +/** + * Basic lock feature for commands. + * + * @author Geoffrey Brier + */ +trait LockableTrait +{ + private $lock = null; + + /** + * Locks a command. + */ + private function lock(string $name = null, bool $blocking = false): bool + { + if (!class_exists(SemaphoreStore::class)) { + throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); + } + + if (null !== $this->lock) { + throw new LogicException('A lock is already in place.'); + } + + if (SemaphoreStore::isSupported()) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); + if (!$this->lock->acquire($blocking)) { + $this->lock = null; + + return false; + } + + return true; + } + + /** + * Releases the command lock if there is one. + */ + private function release() + { + if ($this->lock) { + $this->lock->release(); + $this->lock = null; + } + } +} diff --git a/cacme/vendor/symfony/console/Command/SignalableCommandInterface.php b/cacme/vendor/symfony/console/Command/SignalableCommandInterface.php new file mode 100644 index 0000000..d439728 --- /dev/null +++ b/cacme/vendor/symfony/console/Command/SignalableCommandInterface.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\Console\Command; + +/** + * Interface for command reacting to signal. + * + * @author Grégoire Pineau + */ +interface SignalableCommandInterface +{ + /** + * Returns the list of signals to subscribe. + */ + public function getSubscribedSignals(): array; + + /** + * The method will be called when the application is signaled. + */ + public function handleSignal(int $signal): void; +} diff --git a/cacme/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/cacme/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php new file mode 100644 index 0000000..b6b637c --- /dev/null +++ b/cacme/vendor/symfony/console/CommandLoader/CommandLoaderInterface.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\Console\CommandLoader; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Robin Chalas + */ +interface CommandLoaderInterface +{ + /** + * Loads a command. + * + * @throws CommandNotFoundException + */ + public function get(string $name): Command; + + /** + * Checks if a command exists. + */ + public function has(string $name): bool; + + /** + * @return string[] + */ + public function getNames(): array; +} diff --git a/cacme/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/cacme/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php new file mode 100644 index 0000000..9b26577 --- /dev/null +++ b/cacme/vendor/symfony/console/CommandLoader/ContainerCommandLoader.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\Console\CommandLoader; + +use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * Loads commands from a PSR-11 container. + * + * @author Robin Chalas + */ +class ContainerCommandLoader implements CommandLoaderInterface +{ + private $container; + private array $commandMap; + + /** + * @param array $commandMap An array with command names as keys and service ids as values + */ + public function __construct(ContainerInterface $container, array $commandMap) + { + $this->container = $container; + $this->commandMap = $commandMap; + } + + /** + * {@inheritdoc} + */ + public function get(string $name): Command + { + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return $this->container->get($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function has(string $name): bool + { + return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function getNames(): array + { + return array_keys($this->commandMap); + } +} diff --git a/cacme/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/cacme/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php new file mode 100644 index 0000000..c55dc1d --- /dev/null +++ b/cacme/vendor/symfony/console/CommandLoader/FactoryCommandLoader.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 Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * A simple command loader using factories to instantiate commands lazily. + * + * @author Maxime Steinhausser + */ +class FactoryCommandLoader implements CommandLoaderInterface +{ + private array $factories; + + /** + * @param callable[] $factories Indexed by command names + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + */ + public function has(string $name): bool + { + return isset($this->factories[$name]); + } + + /** + * {@inheritdoc} + */ + public function get(string $name): Command + { + if (!isset($this->factories[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + $factory = $this->factories[$name]; + + return $factory(); + } + + /** + * {@inheritdoc} + */ + public function getNames(): array + { + return array_keys($this->factories); + } +} diff --git a/cacme/vendor/symfony/console/Completion/CompletionInput.php b/cacme/vendor/symfony/console/Completion/CompletionInput.php new file mode 100644 index 0000000..368b945 --- /dev/null +++ b/cacme/vendor/symfony/console/Completion/CompletionInput.php @@ -0,0 +1,249 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion; + +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * An input specialized for shell completion. + * + * This input allows unfinished option names or values and exposes what kind of + * completion is expected. + * + * @author Wouter de Jong + */ +final class CompletionInput extends ArgvInput +{ + public const TYPE_ARGUMENT_VALUE = 'argument_value'; + public const TYPE_OPTION_VALUE = 'option_value'; + public const TYPE_OPTION_NAME = 'option_name'; + public const TYPE_NONE = 'none'; + + private $tokens; + private $currentIndex; + private $completionType; + private $completionName = null; + private $completionValue = ''; + + /** + * Converts a terminal string into tokens. + * + * This is required for shell completions without COMP_WORDS support. + */ + public static function fromString(string $inputStr, int $currentIndex): self + { + preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?tokens = $tokens; + $input->currentIndex = $currentIndex; + + return $input; + } + + /** + * {@inheritdoc} + */ + public function bind(InputDefinition $definition): void + { + parent::bind($definition); + + $relevantToken = $this->getRelevantToken(); + if ('-' === $relevantToken[0]) { + // the current token is an input option: complete either option name or option value + [$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', '']; + + $option = $this->getOptionFromToken($optionToken); + if (null === $option && !$this->isCursorFree()) { + $this->completionType = self::TYPE_OPTION_NAME; + $this->completionValue = $relevantToken; + + return; + } + + if (null !== $option && $option->acceptValue()) { + $this->completionType = self::TYPE_OPTION_VALUE; + $this->completionName = $option->getName(); + $this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : ''); + + return; + } + } + + $previousToken = $this->tokens[$this->currentIndex - 1]; + if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) { + // check if previous option accepted a value + $previousOption = $this->getOptionFromToken($previousToken); + if (null !== $previousOption && $previousOption->acceptValue()) { + $this->completionType = self::TYPE_OPTION_VALUE; + $this->completionName = $previousOption->getName(); + $this->completionValue = $relevantToken; + + return; + } + } + + // complete argument value + $this->completionType = self::TYPE_ARGUMENT_VALUE; + + foreach ($this->definition->getArguments() as $argumentName => $argument) { + if (!isset($this->arguments[$argumentName])) { + break; + } + + $argumentValue = $this->arguments[$argumentName]; + $this->completionName = $argumentName; + if (\is_array($argumentValue)) { + $this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null; + } else { + $this->completionValue = $argumentValue; + } + } + + if ($this->currentIndex >= \count($this->tokens)) { + if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) { + $this->completionName = $argumentName; + $this->completionValue = ''; + } else { + // we've reached the end + $this->completionType = self::TYPE_NONE; + $this->completionName = null; + $this->completionValue = ''; + } + } + } + + /** + * Returns the type of completion required. + * + * TYPE_ARGUMENT_VALUE when completing the value of an input argument + * TYPE_OPTION_VALUE when completing the value of an input option + * TYPE_OPTION_NAME when completing the name of an input option + * TYPE_NONE when nothing should be completed + * + * @return string One of self::TYPE_* constants. TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component + */ + public function getCompletionType(): string + { + return $this->completionType; + } + + /** + * The name of the input option or argument when completing a value. + * + * @return string|null returns null when completing an option name + */ + public function getCompletionName(): ?string + { + return $this->completionName; + } + + /** + * The value already typed by the user (or empty string). + */ + public function getCompletionValue(): string + { + return $this->completionValue; + } + + public function mustSuggestOptionValuesFor(string $optionName): bool + { + return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName(); + } + + public function mustSuggestArgumentValuesFor(string $argumentName): bool + { + return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName(); + } + + protected function parseToken(string $token, bool $parseOptions): bool + { + try { + return parent::parseToken($token, $parseOptions); + } catch (RuntimeException $e) { + // suppress errors, completed input is almost never valid + } + + return $parseOptions; + } + + private function getOptionFromToken(string $optionToken): ?InputOption + { + $optionName = ltrim($optionToken, '-'); + if (!$optionName) { + return null; + } + + if ('-' === ($optionToken[1] ?? ' ')) { + // long option name + return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null; + } + + // short option name + return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null; + } + + /** + * The token of the cursor, or the last token if the cursor is at the end of the input. + */ + private function getRelevantToken(): string + { + return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex]; + } + + /** + * Whether the cursor is "free" (i.e. at the end of the input preceded by a space). + */ + private function isCursorFree(): bool + { + $nrOfTokens = \count($this->tokens); + if ($this->currentIndex > $nrOfTokens) { + throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.'); + } + + return $this->currentIndex >= $nrOfTokens; + } + + public function __toString() + { + $str = ''; + foreach ($this->tokens as $i => $token) { + $str .= $token; + + if ($this->currentIndex === $i) { + $str .= '|'; + } + + $str .= ' '; + } + + if ($this->currentIndex > $i) { + $str .= '|'; + } + + return rtrim($str); + } +} diff --git a/cacme/vendor/symfony/console/Completion/CompletionSuggestions.php b/cacme/vendor/symfony/console/Completion/CompletionSuggestions.php new file mode 100644 index 0000000..7191181 --- /dev/null +++ b/cacme/vendor/symfony/console/Completion/CompletionSuggestions.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 Symfony\Component\Console\Completion; + +use Symfony\Component\Console\Input\InputOption; + +/** + * Stores all completion suggestions for the current input. + * + * @author Wouter de Jong + */ +final class CompletionSuggestions +{ + private $valueSuggestions = []; + private $optionSuggestions = []; + + /** + * Add a suggested value for an input option or argument. + * + * @return $this + */ + public function suggestValue(string|Suggestion $value): static + { + $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value; + + return $this; + } + + /** + * Add multiple suggested values at once for an input option or argument. + * + * @param list $values + * + * @return $this + */ + public function suggestValues(array $values): static + { + foreach ($values as $value) { + $this->suggestValue($value); + } + + return $this; + } + + /** + * Add a suggestion for an input option name. + * + * @return $this + */ + public function suggestOption(InputOption $option): static + { + $this->optionSuggestions[] = $option; + + return $this; + } + + /** + * Add multiple suggestions for input option names at once. + * + * @param InputOption[] $options + * + * @return $this + */ + public function suggestOptions(array $options): static + { + foreach ($options as $option) { + $this->suggestOption($option); + } + + return $this; + } + + /** + * @return InputOption[] + */ + public function getOptionSuggestions(): array + { + return $this->optionSuggestions; + } + + /** + * @return Suggestion[] + */ + public function getValueSuggestions(): array + { + return $this->valueSuggestions; + } +} diff --git a/cacme/vendor/symfony/console/Completion/Output/BashCompletionOutput.php b/cacme/vendor/symfony/console/Completion/Output/BashCompletionOutput.php new file mode 100644 index 0000000..c6f76eb --- /dev/null +++ b/cacme/vendor/symfony/console/Completion/Output/BashCompletionOutput.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 Symfony\Component\Console\Completion\Output; + +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Wouter de Jong + */ +class BashCompletionOutput implements CompletionOutputInterface +{ + public function write(CompletionSuggestions $suggestions, OutputInterface $output): void + { + $values = $suggestions->getValueSuggestions(); + foreach ($suggestions->getOptionSuggestions() as $option) { + $values[] = '--'.$option->getName(); + if ($option->isNegatable()) { + $values[] = '--no-'.$option->getName(); + } + } + $output->writeln(implode("\n", $values)); + } +} diff --git a/cacme/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php b/cacme/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php new file mode 100644 index 0000000..659e596 --- /dev/null +++ b/cacme/vendor/symfony/console/Completion/Output/CompletionOutputInterface.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\Console\Completion\Output; + +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion. + * + * @author Wouter de Jong + */ +interface CompletionOutputInterface +{ + public function write(CompletionSuggestions $suggestions, OutputInterface $output): void; +} diff --git a/cacme/vendor/symfony/console/Completion/Suggestion.php b/cacme/vendor/symfony/console/Completion/Suggestion.php new file mode 100644 index 0000000..ff156f8 --- /dev/null +++ b/cacme/vendor/symfony/console/Completion/Suggestion.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\Console\Completion; + +/** + * Represents a single suggested value. + * + * @author Wouter de Jong + */ +class Suggestion +{ + private string $value; + + public function __construct(string $value) + { + $this->value = $value; + } + + public function getValue(): string + { + return $this->value; + } + + public function __toString(): string + { + return $this->getValue(); + } +} diff --git a/cacme/vendor/symfony/console/ConsoleEvents.php b/cacme/vendor/symfony/console/ConsoleEvents.php new file mode 100644 index 0000000..6ae8f32 --- /dev/null +++ b/cacme/vendor/symfony/console/ConsoleEvents.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\Console; + +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleSignalEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; + +/** + * Contains all events dispatched by an Application. + * + * @author Francesco Levorato + */ +final class ConsoleEvents +{ + /** + * The COMMAND event allows you to attach listeners before any command is + * executed by the console. It also allows you to modify the command, input and output + * before they are handed to the command. + * + * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") + */ + public const COMMAND = 'console.command'; + + /** + * The SIGNAL event allows you to perform some actions + * after the command execution was interrupted. + * + * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent") + */ + public const SIGNAL = 'console.signal'; + + /** + * The TERMINATE event allows you to attach listeners after a command is + * executed by the console. + * + * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") + */ + public const TERMINATE = 'console.terminate'; + + /** + * The ERROR event occurs when an uncaught exception or error appears. + * + * This event allows you to deal with the exception/error or + * to modify the thrown exception. + * + * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") + */ + public const ERROR = 'console.error'; + + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + public const ALIASES = [ + ConsoleCommandEvent::class => self::COMMAND, + ConsoleErrorEvent::class => self::ERROR, + ConsoleSignalEvent::class => self::SIGNAL, + ConsoleTerminateEvent::class => self::TERMINATE, + ]; +} diff --git a/cacme/vendor/symfony/console/Cursor.php b/cacme/vendor/symfony/console/Cursor.php new file mode 100644 index 0000000..995e3d7 --- /dev/null +++ b/cacme/vendor/symfony/console/Cursor.php @@ -0,0 +1,207 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Pierre du Plessis + */ +final class Cursor +{ + private $output; + private $input; + + /** + * @param resource|null $input + */ + public function __construct(OutputInterface $output, $input = null) + { + $this->output = $output; + $this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+')); + } + + /** + * @return $this + */ + public function moveUp(int $lines = 1): static + { + $this->output->write(sprintf("\x1b[%dA", $lines)); + + return $this; + } + + /** + * @return $this + */ + public function moveDown(int $lines = 1): static + { + $this->output->write(sprintf("\x1b[%dB", $lines)); + + return $this; + } + + /** + * @return $this + */ + public function moveRight(int $columns = 1): static + { + $this->output->write(sprintf("\x1b[%dC", $columns)); + + return $this; + } + + /** + * @return $this + */ + public function moveLeft(int $columns = 1): static + { + $this->output->write(sprintf("\x1b[%dD", $columns)); + + return $this; + } + + /** + * @return $this + */ + public function moveToColumn(int $column): static + { + $this->output->write(sprintf("\x1b[%dG", $column)); + + return $this; + } + + /** + * @return $this + */ + public function moveToPosition(int $column, int $row): static + { + $this->output->write(sprintf("\x1b[%d;%dH", $row + 1, $column)); + + return $this; + } + + /** + * @return $this + */ + public function savePosition(): static + { + $this->output->write("\x1b7"); + + return $this; + } + + /** + * @return $this + */ + public function restorePosition(): static + { + $this->output->write("\x1b8"); + + return $this; + } + + /** + * @return $this + */ + public function hide(): static + { + $this->output->write("\x1b[?25l"); + + return $this; + } + + /** + * @return $this + */ + public function show(): static + { + $this->output->write("\x1b[?25h\x1b[?0c"); + + return $this; + } + + /** + * Clears all the output from the current line. + * + * @return $this + */ + public function clearLine(): static + { + $this->output->write("\x1b[2K"); + + return $this; + } + + /** + * Clears all the output from the current line after the current position. + */ + public function clearLineAfter(): self + { + $this->output->write("\x1b[K"); + + return $this; + } + + /** + * Clears all the output from the cursors' current position to the end of the screen. + * + * @return $this + */ + public function clearOutput(): static + { + $this->output->write("\x1b[0J"); + + return $this; + } + + /** + * Clears the entire screen. + * + * @return $this + */ + public function clearScreen(): static + { + $this->output->write("\x1b[2J"); + + return $this; + } + + /** + * Returns the current cursor position as x,y coordinates. + */ + public function getCurrentPosition(): array + { + static $isTtySupported; + + if (null === $isTtySupported && \function_exists('proc_open')) { + $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); + } + + if (!$isTtySupported) { + return [1, 1]; + } + + $sttyMode = shell_exec('stty -g'); + shell_exec('stty -icanon -echo'); + + @fwrite($this->input, "\033[6n"); + + $code = trim(fread($this->input, 1024)); + + shell_exec(sprintf('stty %s', $sttyMode)); + + sscanf($code, "\033[%d;%dR", $row, $col); + + return [$col, $row]; + } +} diff --git a/cacme/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/cacme/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php new file mode 100644 index 0000000..cfb2049 --- /dev/null +++ b/cacme/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.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\Console\DependencyInjection; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\LazyCommand; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Registers console commands. + * + * @author Grégoire Pineau + */ +class AddConsoleCommandPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $commandServices = $container->findTaggedServiceIds('console.command', true); + $lazyCommandMap = []; + $lazyCommandRefs = []; + $serviceIds = []; + + foreach ($commandServices as $id => $tags) { + $definition = $container->getDefinition($id); + $definition->addTag('container.no_preload'); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); + + if (isset($tags[0]['command'])) { + $aliases = $tags[0]['command']; + } else { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); + } + $aliases = str_replace('%', '%%', $class::getDefaultName() ?? ''); + } + + $aliases = explode('|', $aliases ?? ''); + $commandName = array_shift($aliases); + + if ($isHidden = '' === $commandName) { + $commandName = array_shift($aliases); + } + + if (null === $commandName) { + if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag('container.private')) { + $commandId = 'console.command.public_alias.'.$id; + $container->setAlias($commandId, $id)->setPublic(true); + $id = $commandId; + } + $serviceIds[] = $id; + + continue; + } + + $description = $tags[0]['description'] ?? null; + + unset($tags[0]); + $lazyCommandMap[$commandName] = $id; + $lazyCommandRefs[$id] = new TypedReference($id, $class); + + foreach ($aliases as $alias) { + $lazyCommandMap[$alias] = $id; + } + + foreach ($tags as $tag) { + if (isset($tag['command'])) { + $aliases[] = $tag['command']; + $lazyCommandMap[$tag['command']] = $id; + } + + $description = $description ?? $tag['description'] ?? null; + } + + $definition->addMethodCall('setName', [$commandName]); + + if ($aliases) { + $definition->addMethodCall('setAliases', [$aliases]); + } + + if ($isHidden) { + $definition->addMethodCall('setHidden', [true]); + } + + if (!$description) { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); + } + $description = str_replace('%', '%%', $class::getDefaultDescription() ?? ''); + } + + if ($description) { + $definition->addMethodCall('setDescription', [$description]); + + $container->register('.'.$id.'.lazy', LazyCommand::class) + ->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]); + + $lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy'); + } + } + + $container + ->register('console.command_loader', ContainerCommandLoader::class) + ->setPublic(true) + ->addTag('container.no_preload') + ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); + + $container->setParameter('console.command.ids', $serviceIds); + } +} diff --git a/cacme/vendor/symfony/console/Descriptor/ApplicationDescription.php b/cacme/vendor/symfony/console/Descriptor/ApplicationDescription.php new file mode 100644 index 0000000..2fd311a --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/ApplicationDescription.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 Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Jean-François Simon + * + * @internal + */ +class ApplicationDescription +{ + public const GLOBAL_NAMESPACE = '_global'; + + private $application; + private ?string $namespace; + private bool $showHidden; + private array $namespaces; + + /** + * @var array + */ + private array $commands; + + /** + * @var array + */ + private array $aliases = []; + + public function __construct(Application $application, string $namespace = null, bool $showHidden = false) + { + $this->application = $application; + $this->namespace = $namespace; + $this->showHidden = $showHidden; + } + + public function getNamespaces(): array + { + if (!isset($this->namespaces)) { + $this->inspectApplication(); + } + + return $this->namespaces; + } + + /** + * @return Command[] + */ + public function getCommands(): array + { + if (!isset($this->commands)) { + $this->inspectApplication(); + } + + return $this->commands; + } + + /** + * @throws CommandNotFoundException + */ + public function getCommand(string $name): Command + { + if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return $this->commands[$name] ?? $this->aliases[$name]; + } + + private function inspectApplication() + { + $this->commands = []; + $this->namespaces = []; + + $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); + foreach ($this->sortCommands($all) as $namespace => $commands) { + $names = []; + + /** @var Command $command */ + foreach ($commands as $name => $command) { + if (!$command->getName() || (!$this->showHidden && $command->isHidden())) { + continue; + } + + if ($command->getName() === $name) { + $this->commands[$name] = $command; + } else { + $this->aliases[$name] = $command; + } + + $names[] = $name; + } + + $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names]; + } + } + + private function sortCommands(array $commands): array + { + $namespacedCommands = []; + $globalCommands = []; + $sortedCommands = []; + foreach ($commands as $name => $command) { + $key = $this->application->extractNamespace($name, 1); + if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { + $globalCommands[$name] = $command; + } else { + $namespacedCommands[$key][$name] = $command; + } + } + + if ($globalCommands) { + ksort($globalCommands); + $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; + } + + if ($namespacedCommands) { + ksort($namespacedCommands, \SORT_STRING); + foreach ($namespacedCommands as $key => $commandsSet) { + ksort($commandsSet); + $sortedCommands[$key] = $commandsSet; + } + } + + return $sortedCommands; + } +} diff --git a/cacme/vendor/symfony/console/Descriptor/Descriptor.php b/cacme/vendor/symfony/console/Descriptor/Descriptor.php new file mode 100644 index 0000000..a364830 --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/Descriptor.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\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Jean-François Simon + * + * @internal + */ +abstract class Descriptor implements DescriptorInterface +{ + /** + * @var OutputInterface + */ + protected $output; + + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, object $object, array $options = []) + { + $this->output = $output; + + switch (true) { + case $object instanceof InputArgument: + $this->describeInputArgument($object, $options); + break; + case $object instanceof InputOption: + $this->describeInputOption($object, $options); + break; + case $object instanceof InputDefinition: + $this->describeInputDefinition($object, $options); + break; + case $object instanceof Command: + $this->describeCommand($object, $options); + break; + case $object instanceof Application: + $this->describeApplication($object, $options); + break; + default: + throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))); + } + } + + /** + * Writes content to output. + */ + protected function write(string $content, bool $decorated = false) + { + $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); + } + + /** + * Describes an InputArgument instance. + */ + abstract protected function describeInputArgument(InputArgument $argument, array $options = []); + + /** + * Describes an InputOption instance. + */ + abstract protected function describeInputOption(InputOption $option, array $options = []); + + /** + * Describes an InputDefinition instance. + */ + abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); + + /** + * Describes a Command instance. + */ + abstract protected function describeCommand(Command $command, array $options = []); + + /** + * Describes an Application instance. + */ + abstract protected function describeApplication(Application $application, array $options = []); +} diff --git a/cacme/vendor/symfony/console/Descriptor/DescriptorInterface.php b/cacme/vendor/symfony/console/Descriptor/DescriptorInterface.php new file mode 100644 index 0000000..ebea303 --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/DescriptorInterface.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\Console\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Descriptor interface. + * + * @author Jean-François Simon + */ +interface DescriptorInterface +{ + public function describe(OutputInterface $output, object $object, array $options = []); +} diff --git a/cacme/vendor/symfony/console/Descriptor/JsonDescriptor.php b/cacme/vendor/symfony/console/Descriptor/JsonDescriptor.php new file mode 100644 index 0000000..1d28659 --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/JsonDescriptor.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 Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * JSON descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class JsonDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->writeData($this->getInputArgumentData($argument), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $this->writeData($this->getInputOptionData($option), $options); + if ($option->isNegatable()) { + $this->writeData($this->getInputOptionData($option, true), $options); + } + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $this->writeData($this->getInputDefinitionData($definition), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $this->writeData($this->getCommandData($command, $options['short'] ?? false), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = $options['namespace'] ?? null; + $description = new ApplicationDescription($application, $describedNamespace, true); + $commands = []; + + foreach ($description->getCommands() as $command) { + $commands[] = $this->getCommandData($command, $options['short'] ?? false); + } + + $data = []; + if ('UNKNOWN' !== $application->getName()) { + $data['application']['name'] = $application->getName(); + if ('UNKNOWN' !== $application->getVersion()) { + $data['application']['version'] = $application->getVersion(); + } + } + + $data['commands'] = $commands; + + if ($describedNamespace) { + $data['namespace'] = $describedNamespace; + } else { + $data['namespaces'] = array_values($description->getNamespaces()); + } + + $this->writeData($data, $options); + } + + /** + * Writes data as json. + */ + private function writeData(array $data, array $options) + { + $flags = $options['json_encoding'] ?? 0; + + $this->write(json_encode($data, $flags)); + } + + private function getInputArgumentData(InputArgument $argument): array + { + return [ + 'name' => $argument->getName(), + 'is_required' => $argument->isRequired(), + 'is_array' => $argument->isArray(), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), + 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), + ]; + } + + private function getInputOptionData(InputOption $option, bool $negated = false): array + { + return $negated ? [ + 'name' => '--no-'.$option->getName(), + 'shortcut' => '', + 'accept_value' => false, + 'is_value_required' => false, + 'is_multiple' => false, + 'description' => 'Negate the "--'.$option->getName().'" option', + 'default' => false, + ] : [ + 'name' => '--'.$option->getName(), + 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', + 'accept_value' => $option->acceptValue(), + 'is_value_required' => $option->isValueRequired(), + 'is_multiple' => $option->isArray(), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), + 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), + ]; + } + + private function getInputDefinitionData(InputDefinition $definition): array + { + $inputArguments = []; + foreach ($definition->getArguments() as $name => $argument) { + $inputArguments[$name] = $this->getInputArgumentData($argument); + } + + $inputOptions = []; + foreach ($definition->getOptions() as $name => $option) { + $inputOptions[$name] = $this->getInputOptionData($option); + if ($option->isNegatable()) { + $inputOptions['no-'.$name] = $this->getInputOptionData($option, true); + } + } + + return ['arguments' => $inputArguments, 'options' => $inputOptions]; + } + + private function getCommandData(Command $command, bool $short = false): array + { + $data = [ + 'name' => $command->getName(), + 'description' => $command->getDescription(), + ]; + + if ($short) { + $data += [ + 'usage' => $command->getAliases(), + ]; + } else { + $command->mergeApplicationDefinition(false); + + $data += [ + 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), + 'help' => $command->getProcessedHelp(), + 'definition' => $this->getInputDefinitionData($command->getDefinition()), + ]; + } + + $data['hidden'] = $command->isHidden(); + + return $data; + } +} diff --git a/cacme/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/cacme/vendor/symfony/console/Descriptor/MarkdownDescriptor.php new file mode 100644 index 0000000..21ceca6 --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/MarkdownDescriptor.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 Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Markdown descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class MarkdownDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, object $object, array $options = []) + { + $decorated = $output->isDecorated(); + $output->setDecorated(false); + + parent::describe($output, $object, $options); + + $output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + protected function write(string $content, bool $decorated = true) + { + parent::write($content, $decorated); + } + + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->write( + '#### `'.($argument->getName() ?: '')."`\n\n" + .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') + .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" + .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" + .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' + ); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $name = '--'.$option->getName(); + if ($option->isNegatable()) { + $name .= '|--no-'.$option->getName(); + } + if ($option->getShortcut()) { + $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; + } + + $this->write( + '#### `'.$name.'`'."\n\n" + .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') + .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" + .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" + .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" + .'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n" + .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' + ); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + if ($showArguments = \count($definition->getArguments()) > 0) { + $this->write('### Arguments'); + foreach ($definition->getArguments() as $argument) { + $this->write("\n\n"); + if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { + $this->write($describeInputArgument); + } + } + } + + if (\count($definition->getOptions()) > 0) { + if ($showArguments) { + $this->write("\n\n"); + } + + $this->write('### Options'); + foreach ($definition->getOptions() as $option) { + $this->write("\n\n"); + if (null !== $describeInputOption = $this->describeInputOption($option)) { + $this->write($describeInputOption); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + if ($options['short'] ?? false) { + $this->write( + '`'.$command->getName()."`\n" + .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + .'### Usage'."\n\n" + .array_reduce($command->getAliases(), function ($carry, $usage) { + return $carry.'* `'.$usage.'`'."\n"; + }) + ); + + return; + } + + $command->mergeApplicationDefinition(false); + + $this->write( + '`'.$command->getName()."`\n" + .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + .'### Usage'."\n\n" + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { + return $carry.'* `'.$usage.'`'."\n"; + }) + ); + + if ($help = $command->getProcessedHelp()) { + $this->write("\n"); + $this->write($help); + } + + $definition = $command->getDefinition(); + if ($definition->getOptions() || $definition->getArguments()) { + $this->write("\n\n"); + $this->describeInputDefinition($definition); + } + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = $options['namespace'] ?? null; + $description = new ApplicationDescription($application, $describedNamespace); + $title = $this->getApplicationTitle($application); + + $this->write($title."\n".str_repeat('=', Helper::width($title))); + + foreach ($description->getNamespaces() as $namespace) { + if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { + $this->write("\n\n"); + $this->write('**'.$namespace['id'].':**'); + } + + $this->write("\n\n"); + $this->write(implode("\n", array_map(function ($commandName) use ($description) { + return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); + }, $namespace['commands']))); + } + + foreach ($description->getCommands() as $command) { + $this->write("\n\n"); + if (null !== $describeCommand = $this->describeCommand($command, $options)) { + $this->write($describeCommand); + } + } + } + + private function getApplicationTitle(Application $application): string + { + if ('UNKNOWN' !== $application->getName()) { + if ('UNKNOWN' !== $application->getVersion()) { + return sprintf('%s %s', $application->getName(), $application->getVersion()); + } + + return $application->getName(); + } + + return 'Console Tool'; + } +} diff --git a/cacme/vendor/symfony/console/Descriptor/TextDescriptor.php b/cacme/vendor/symfony/console/Descriptor/TextDescriptor.php new file mode 100644 index 0000000..3f309f5 --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/TextDescriptor.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 Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * Text descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class TextDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { + $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); + } else { + $default = ''; + } + + $totalWidth = $options['total_width'] ?? Helper::width($argument->getName()); + $spacingWidth = $totalWidth - \strlen($argument->getName()); + + $this->writeText(sprintf(' %s %s%s%s', + $argument->getName(), + str_repeat(' ', $spacingWidth), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), + $default + ), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { + $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); + } else { + $default = ''; + } + + $value = ''; + if ($option->acceptValue()) { + $value = '='.strtoupper($option->getName()); + + if ($option->isValueOptional()) { + $value = '['.$value.']'; + } + } + + $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]); + $synopsis = sprintf('%s%s', + $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', + sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value) + ); + + $spacingWidth = $totalWidth - Helper::width($synopsis); + + $this->writeText(sprintf(' %s %s%s%s%s', + $synopsis, + str_repeat(' ', $spacingWidth), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), + $default, + $option->isArray() ? ' (multiple values allowed)' : '' + ), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); + foreach ($definition->getArguments() as $argument) { + $totalWidth = max($totalWidth, Helper::width($argument->getName())); + } + + if ($definition->getArguments()) { + $this->writeText('Arguments:', $options); + $this->writeText("\n"); + foreach ($definition->getArguments() as $argument) { + $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); + $this->writeText("\n"); + } + } + + if ($definition->getArguments() && $definition->getOptions()) { + $this->writeText("\n"); + } + + if ($definition->getOptions()) { + $laterOptions = []; + + $this->writeText('Options:', $options); + foreach ($definition->getOptions() as $option) { + if (\strlen($option->getShortcut() ?? '') > 1) { + $laterOptions[] = $option; + continue; + } + $this->writeText("\n"); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); + } + foreach ($laterOptions as $option) { + $this->writeText("\n"); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $command->mergeApplicationDefinition(false); + + if ($description = $command->getDescription()) { + $this->writeText('Description:', $options); + $this->writeText("\n"); + $this->writeText(' '.$description); + $this->writeText("\n\n"); + } + + $this->writeText('Usage:', $options); + foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { + $this->writeText("\n"); + $this->writeText(' '.OutputFormatter::escape($usage), $options); + } + $this->writeText("\n"); + + $definition = $command->getDefinition(); + if ($definition->getOptions() || $definition->getArguments()) { + $this->writeText("\n"); + $this->describeInputDefinition($definition, $options); + $this->writeText("\n"); + } + + $help = $command->getProcessedHelp(); + if ($help && $help !== $description) { + $this->writeText("\n"); + $this->writeText('Help:', $options); + $this->writeText("\n"); + $this->writeText(' '.str_replace("\n", "\n ", $help), $options); + $this->writeText("\n"); + } + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = $options['namespace'] ?? null; + $description = new ApplicationDescription($application, $describedNamespace); + + if (isset($options['raw_text']) && $options['raw_text']) { + $width = $this->getColumnWidth($description->getCommands()); + + foreach ($description->getCommands() as $command) { + $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); + $this->writeText("\n"); + } + } else { + if ('' != $help = $application->getHelp()) { + $this->writeText("$help\n\n", $options); + } + + $this->writeText("Usage:\n", $options); + $this->writeText(" command [options] [arguments]\n\n", $options); + + $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); + + $this->writeText("\n"); + $this->writeText("\n"); + + $commands = $description->getCommands(); + $namespaces = $description->getNamespaces(); + if ($describedNamespace && $namespaces) { + // make sure all alias commands are included when describing a specific namespace + $describedNamespaceInfo = reset($namespaces); + foreach ($describedNamespaceInfo['commands'] as $name) { + $commands[$name] = $description->getCommand($name); + } + } + + // calculate max. width based on available commands per namespace + $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { + return array_intersect($namespace['commands'], array_keys($commands)); + }, array_values($namespaces))))); + + if ($describedNamespace) { + $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); + } else { + $this->writeText('Available commands:', $options); + } + + foreach ($namespaces as $namespace) { + $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { + return isset($commands[$name]); + }); + + if (!$namespace['commands']) { + continue; + } + + if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { + $this->writeText("\n"); + $this->writeText(' '.$namespace['id'].'', $options); + } + + foreach ($namespace['commands'] as $name) { + $this->writeText("\n"); + $spacingWidth = $width - Helper::width($name); + $command = $commands[$name]; + $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; + $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); + } + } + + $this->writeText("\n"); + } + } + + /** + * {@inheritdoc} + */ + private function writeText(string $content, array $options = []) + { + $this->write( + isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, + isset($options['raw_output']) ? !$options['raw_output'] : true + ); + } + + /** + * Formats command aliases to show them in the command description. + */ + private function getCommandAliasesText(Command $command): string + { + $text = ''; + $aliases = $command->getAliases(); + + if ($aliases) { + $text = '['.implode('|', $aliases).'] '; + } + + return $text; + } + + /** + * Formats input option/argument default value. + */ + private function formatDefaultValue(mixed $default): string + { + if (\INF === $default) { + return 'INF'; + } + + if (\is_string($default)) { + $default = OutputFormatter::escape($default); + } elseif (\is_array($default)) { + foreach ($default as $key => $value) { + if (\is_string($value)) { + $default[$key] = OutputFormatter::escape($value); + } + } + } + + return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); + } + + /** + * @param array $commands + */ + private function getColumnWidth(array $commands): int + { + $widths = []; + + foreach ($commands as $command) { + if ($command instanceof Command) { + $widths[] = Helper::width($command->getName()); + foreach ($command->getAliases() as $alias) { + $widths[] = Helper::width($alias); + } + } else { + $widths[] = Helper::width($command); + } + } + + return $widths ? max($widths) + 2 : 0; + } + + /** + * @param InputOption[] $options + */ + private function calculateTotalWidthForOptions(array $options): int + { + $totalWidth = 0; + foreach ($options as $option) { + // "-" + shortcut + ", --" + name + $nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName()); + if ($option->isNegatable()) { + $nameLength += 6 + Helper::width($option->getName()); // |--no- + name + } elseif ($option->acceptValue()) { + $valueLength = 1 + Helper::width($option->getName()); // = + value + $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] + + $nameLength += $valueLength; + } + $totalWidth = max($totalWidth, $nameLength); + } + + return $totalWidth; + } +} diff --git a/cacme/vendor/symfony/console/Descriptor/XmlDescriptor.php b/cacme/vendor/symfony/console/Descriptor/XmlDescriptor.php new file mode 100644 index 0000000..4f7cd8b --- /dev/null +++ b/cacme/vendor/symfony/console/Descriptor/XmlDescriptor.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 Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * XML descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class XmlDescriptor extends Descriptor +{ + public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($definitionXML = $dom->createElement('definition')); + + $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); + foreach ($definition->getArguments() as $argument) { + $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); + } + + $definitionXML->appendChild($optionsXML = $dom->createElement('options')); + foreach ($definition->getOptions() as $option) { + $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); + } + + return $dom; + } + + public function getCommandDocument(Command $command, bool $short = false): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($commandXML = $dom->createElement('command')); + + $commandXML->setAttribute('id', $command->getName()); + $commandXML->setAttribute('name', $command->getName()); + $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); + + $commandXML->appendChild($usagesXML = $dom->createElement('usages')); + + $commandXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); + + if ($short) { + foreach ($command->getAliases() as $usage) { + $usagesXML->appendChild($dom->createElement('usage', $usage)); + } + } else { + $command->mergeApplicationDefinition(false); + + foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { + $usagesXML->appendChild($dom->createElement('usage', $usage)); + } + + $commandXML->appendChild($helpXML = $dom->createElement('help')); + $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); + + $definitionXML = $this->getInputDefinitionDocument($command->getDefinition()); + $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); + } + + return $dom; + } + + public function getApplicationDocument(Application $application, string $namespace = null, bool $short = false): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($rootXml = $dom->createElement('symfony')); + + if ('UNKNOWN' !== $application->getName()) { + $rootXml->setAttribute('name', $application->getName()); + if ('UNKNOWN' !== $application->getVersion()) { + $rootXml->setAttribute('version', $application->getVersion()); + } + } + + $rootXml->appendChild($commandsXML = $dom->createElement('commands')); + + $description = new ApplicationDescription($application, $namespace, true); + + if ($namespace) { + $commandsXML->setAttribute('namespace', $namespace); + } + + foreach ($description->getCommands() as $command) { + $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short)); + } + + if (!$namespace) { + $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); + + foreach ($description->getNamespaces() as $namespaceDescription) { + $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); + $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); + + foreach ($namespaceDescription['commands'] as $name) { + $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); + $commandXML->appendChild($dom->createTextNode($name)); + } + } + } + + return $dom; + } + + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->writeDocument($this->getInputArgumentDocument($argument)); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $this->writeDocument($this->getInputOptionDocument($option)); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $this->writeDocument($this->getInputDefinitionDocument($definition)); + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false)); + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false)); + } + + /** + * Appends document children to parent node. + */ + private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) + { + foreach ($importedParent->childNodes as $childNode) { + $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); + } + } + + /** + * Writes DOM document. + */ + private function writeDocument(\DOMDocument $dom) + { + $dom->formatOutput = true; + $this->write($dom->saveXML()); + } + + private function getInputArgumentDocument(InputArgument $argument): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + $dom->appendChild($objectXML = $dom->createElement('argument')); + $objectXML->setAttribute('name', $argument->getName()); + $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); + $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); + + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); + $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + + return $dom; + } + + private function getInputOptionDocument(InputOption $option): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + $dom->appendChild($objectXML = $dom->createElement('option')); + $objectXML->setAttribute('name', '--'.$option->getName()); + $pos = strpos($option->getShortcut() ?? '', '|'); + if (false !== $pos) { + $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); + $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); + } else { + $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); + } + $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); + $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); + $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); + + if ($option->acceptValue()) { + $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); + + if (!empty($defaults)) { + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + } + } + + if ($option->isNegatable()) { + $dom->appendChild($objectXML = $dom->createElement('option')); + $objectXML->setAttribute('name', '--no-'.$option->getName()); + $objectXML->setAttribute('shortcut', ''); + $objectXML->setAttribute('accept_value', 0); + $objectXML->setAttribute('is_value_required', 0); + $objectXML->setAttribute('is_multiple', 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode('Negate the "--'.$option->getName().'" option')); + } + + return $dom; + } +} diff --git a/cacme/vendor/symfony/console/Event/ConsoleCommandEvent.php b/cacme/vendor/symfony/console/Event/ConsoleCommandEvent.php new file mode 100644 index 0000000..31c9ee9 --- /dev/null +++ b/cacme/vendor/symfony/console/Event/ConsoleCommandEvent.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\Console\Event; + +/** + * Allows to do things before the command is executed, like skipping the command or changing the input. + * + * @author Fabien Potencier + */ +final class ConsoleCommandEvent extends ConsoleEvent +{ + /** + * The return code for skipped commands, this will also be passed into the terminate event. + */ + public const RETURN_CODE_DISABLED = 113; + + /** + * Indicates if the command should be run or skipped. + */ + private bool $commandShouldRun = true; + + /** + * Disables the command, so it won't be run. + */ + public function disableCommand(): bool + { + return $this->commandShouldRun = false; + } + + public function enableCommand(): bool + { + return $this->commandShouldRun = true; + } + + /** + * Returns true if the command is runnable, false otherwise. + */ + public function commandShouldRun(): bool + { + return $this->commandShouldRun; + } +} diff --git a/cacme/vendor/symfony/console/Event/ConsoleErrorEvent.php b/cacme/vendor/symfony/console/Event/ConsoleErrorEvent.php new file mode 100644 index 0000000..19bd4bf --- /dev/null +++ b/cacme/vendor/symfony/console/Event/ConsoleErrorEvent.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\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to handle throwables thrown while running a command. + * + * @author Wouter de Jong + */ +final class ConsoleErrorEvent extends ConsoleEvent +{ + private \Throwable $error; + private int $exitCode; + + public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) + { + parent::__construct($command, $input, $output); + + $this->error = $error; + } + + public function getError(): \Throwable + { + return $this->error; + } + + public function setError(\Throwable $error): void + { + $this->error = $error; + } + + public function setExitCode(int $exitCode): void + { + $this->exitCode = $exitCode; + + $r = new \ReflectionProperty($this->error, 'code'); + $r->setAccessible(true); + $r->setValue($this->error, $this->exitCode); + } + + public function getExitCode(): int + { + return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); + } +} diff --git a/cacme/vendor/symfony/console/Event/ConsoleEvent.php b/cacme/vendor/symfony/console/Event/ConsoleEvent.php new file mode 100644 index 0000000..56b8a9a --- /dev/null +++ b/cacme/vendor/symfony/console/Event/ConsoleEvent.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\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * Allows to inspect input and output of a command. + * + * @author Francesco Levorato + */ +class ConsoleEvent extends Event +{ + protected $command; + + private $input; + private $output; + + public function __construct(?Command $command, InputInterface $input, OutputInterface $output) + { + $this->command = $command; + $this->input = $input; + $this->output = $output; + } + + /** + * Gets the command that is executed. + */ + public function getCommand(): ?Command + { + return $this->command; + } + + /** + * Gets the input instance. + */ + public function getInput(): InputInterface + { + return $this->input; + } + + /** + * Gets the output instance. + */ + public function getOutput(): OutputInterface + { + return $this->output; + } +} diff --git a/cacme/vendor/symfony/console/Event/ConsoleSignalEvent.php b/cacme/vendor/symfony/console/Event/ConsoleSignalEvent.php new file mode 100644 index 0000000..766af69 --- /dev/null +++ b/cacme/vendor/symfony/console/Event/ConsoleSignalEvent.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\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author marie + */ +final class ConsoleSignalEvent extends ConsoleEvent +{ + private int $handlingSignal; + + public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal) + { + parent::__construct($command, $input, $output); + $this->handlingSignal = $handlingSignal; + } + + public function getHandlingSignal(): int + { + return $this->handlingSignal; + } +} diff --git a/cacme/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/cacme/vendor/symfony/console/Event/ConsoleTerminateEvent.php new file mode 100644 index 0000000..de63c8f --- /dev/null +++ b/cacme/vendor/symfony/console/Event/ConsoleTerminateEvent.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\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to manipulate the exit code of a command after its execution. + * + * @author Francesco Levorato + */ +final class ConsoleTerminateEvent extends ConsoleEvent +{ + private int $exitCode; + + public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode) + { + parent::__construct($command, $input, $output); + + $this->setExitCode($exitCode); + } + + public function setExitCode(int $exitCode): void + { + $this->exitCode = $exitCode; + } + + public function getExitCode(): int + { + return $this->exitCode; + } +} diff --git a/cacme/vendor/symfony/console/EventListener/ErrorListener.php b/cacme/vendor/symfony/console/EventListener/ErrorListener.php new file mode 100644 index 0000000..61bd9d3 --- /dev/null +++ b/cacme/vendor/symfony/console/EventListener/ErrorListener.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\Console\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * @author James Halsall + * @author Robin Chalas + */ +class ErrorListener implements EventSubscriberInterface +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + public function onConsoleError(ConsoleErrorEvent $event) + { + if (null === $this->logger) { + return; + } + + $error = $event->getError(); + + if (!$inputString = $this->getInputString($event)) { + $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); + + return; + } + + $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); + } + + public function onConsoleTerminate(ConsoleTerminateEvent $event) + { + if (null === $this->logger) { + return; + } + + $exitCode = $event->getExitCode(); + + if (0 === $exitCode) { + return; + } + + if (!$inputString = $this->getInputString($event)) { + $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); + + return; + } + + $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); + } + + public static function getSubscribedEvents(): array + { + return [ + ConsoleEvents::ERROR => ['onConsoleError', -128], + ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128], + ]; + } + + private static function getInputString(ConsoleEvent $event): ?string + { + $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; + $input = $event->getInput(); + + if ($input instanceof \Stringable) { + if ($commandName) { + return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); + } + + return (string) $input; + } + + return $commandName; + } +} diff --git a/cacme/vendor/symfony/console/Exception/CommandNotFoundException.php b/cacme/vendor/symfony/console/Exception/CommandNotFoundException.php new file mode 100644 index 0000000..1e9f1c7 --- /dev/null +++ b/cacme/vendor/symfony/console/Exception/CommandNotFoundException.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\Console\Exception; + +/** + * Represents an incorrect command name typed in the console. + * + * @author Jérôme Tamarelle + */ +class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface +{ + private array $alternatives; + + /** + * @param string $message Exception message to throw + * @param string[] $alternatives List of similar defined names + * @param int $code Exception code + * @param \Throwable|null $previous Previous exception used for the exception chaining + */ + public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->alternatives = $alternatives; + } + + /** + * @return string[] + */ + public function getAlternatives(): array + { + return $this->alternatives; + } +} diff --git a/cacme/vendor/symfony/console/Exception/ExceptionInterface.php b/cacme/vendor/symfony/console/Exception/ExceptionInterface.php new file mode 100644 index 0000000..1624e13 --- /dev/null +++ b/cacme/vendor/symfony/console/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\Console\Exception; + +/** + * ExceptionInterface. + * + * @author Jérôme Tamarelle + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/cacme/vendor/symfony/console/Exception/InvalidArgumentException.php b/cacme/vendor/symfony/console/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..07cc0b6 --- /dev/null +++ b/cacme/vendor/symfony/console/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 Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/console/Exception/InvalidOptionException.php b/cacme/vendor/symfony/console/Exception/InvalidOptionException.php new file mode 100644 index 0000000..5cf6279 --- /dev/null +++ b/cacme/vendor/symfony/console/Exception/InvalidOptionException.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\Console\Exception; + +/** + * Represents an incorrect option name or value typed in the console. + * + * @author Jérôme Tamarelle + */ +class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/console/Exception/LogicException.php b/cacme/vendor/symfony/console/Exception/LogicException.php new file mode 100644 index 0000000..fc37b8d --- /dev/null +++ b/cacme/vendor/symfony/console/Exception/LogicException.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 Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/console/Exception/MissingInputException.php b/cacme/vendor/symfony/console/Exception/MissingInputException.php new file mode 100644 index 0000000..04f02ad --- /dev/null +++ b/cacme/vendor/symfony/console/Exception/MissingInputException.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\Console\Exception; + +/** + * Represents failure to read input from stdin. + * + * @author Gabriel Ostrolucký + */ +class MissingInputException extends RuntimeException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/console/Exception/NamespaceNotFoundException.php b/cacme/vendor/symfony/console/Exception/NamespaceNotFoundException.php new file mode 100644 index 0000000..dd16e45 --- /dev/null +++ b/cacme/vendor/symfony/console/Exception/NamespaceNotFoundException.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\Console\Exception; + +/** + * Represents an incorrect namespace typed in the console. + * + * @author Pierre du Plessis + */ +class NamespaceNotFoundException extends CommandNotFoundException +{ +} diff --git a/cacme/vendor/symfony/console/Exception/RuntimeException.php b/cacme/vendor/symfony/console/Exception/RuntimeException.php new file mode 100644 index 0000000..51d7d80 --- /dev/null +++ b/cacme/vendor/symfony/console/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 Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/console/Formatter/NullOutputFormatter.php b/cacme/vendor/symfony/console/Formatter/NullOutputFormatter.php new file mode 100644 index 0000000..d770e14 --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/NullOutputFormatter.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 Symfony\Component\Console\Formatter; + +/** + * @author Tien Xuan Vo + */ +final class NullOutputFormatter implements OutputFormatterInterface +{ + private $style; + + /** + * {@inheritdoc} + */ + public function format(?string $message): ?string + { + return null; + } + + /** + * {@inheritdoc} + */ + public function getStyle(string $name): OutputFormatterStyleInterface + { + // to comply with the interface we must return a OutputFormatterStyleInterface + return $this->style ?? $this->style = new NullOutputFormatterStyle(); + } + + /** + * {@inheritdoc} + */ + public function hasStyle(string $name): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isDecorated(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setStyle(string $name, OutputFormatterStyleInterface $style): void + { + // do nothing + } +} diff --git a/cacme/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php b/cacme/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php new file mode 100644 index 0000000..9232510 --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/NullOutputFormatterStyle.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 Symfony\Component\Console\Formatter; + +/** + * @author Tien Xuan Vo + */ +final class NullOutputFormatterStyle implements OutputFormatterStyleInterface +{ + /** + * {@inheritdoc} + */ + public function apply(string $text): string + { + return $text; + } + + /** + * {@inheritdoc} + */ + public function setBackground(string $color = null): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setForeground(string $color = null): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setOption(string $option): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setOptions(array $options): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function unsetOption(string $option): void + { + // do nothing + } +} diff --git a/cacme/vendor/symfony/console/Formatter/OutputFormatter.php b/cacme/vendor/symfony/console/Formatter/OutputFormatter.php new file mode 100644 index 0000000..4a6ae91 --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/OutputFormatter.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Formatter class for console output. + * + * @author Konstantin Kudryashov + * @author Roland Franssen + */ +class OutputFormatter implements WrappableOutputFormatterInterface +{ + private bool $decorated; + private array $styles = []; + private $styleStack; + + public function __clone() + { + $this->styleStack = clone $this->styleStack; + foreach ($this->styles as $key => $value) { + $this->styles[$key] = clone $value; + } + } + + /** + * Escapes "<" and ">" special chars in given text. + */ + public static function escape(string $text): string + { + $text = preg_replace('/([^\\\\]|^)([<>])/', '$1\\\\$2', $text); + + return self::escapeTrailingBackslash($text); + } + + /** + * Escapes trailing "\" in given text. + * + * @internal + */ + public static function escapeTrailingBackslash(string $text): string + { + if (str_ends_with($text, '\\')) { + $len = \strlen($text); + $text = rtrim($text, '\\'); + $text = str_replace("\0", '', $text); + $text .= str_repeat("\0", $len - \strlen($text)); + } + + return $text; + } + + /** + * Initializes console output formatter. + * + * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances + */ + public function __construct(bool $decorated = false, array $styles = []) + { + $this->decorated = $decorated; + + $this->setStyle('error', new OutputFormatterStyle('white', 'red')); + $this->setStyle('info', new OutputFormatterStyle('green')); + $this->setStyle('comment', new OutputFormatterStyle('yellow')); + $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); + + foreach ($styles as $name => $style) { + $this->setStyle($name, $style); + } + + $this->styleStack = new OutputFormatterStyleStack(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function isDecorated(): bool + { + return $this->decorated; + } + + /** + * {@inheritdoc} + */ + public function setStyle(string $name, OutputFormatterStyleInterface $style) + { + $this->styles[strtolower($name)] = $style; + } + + /** + * {@inheritdoc} + */ + public function hasStyle(string $name): bool + { + return isset($this->styles[strtolower($name)]); + } + + /** + * {@inheritdoc} + */ + public function getStyle(string $name): OutputFormatterStyleInterface + { + if (!$this->hasStyle($name)) { + throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name)); + } + + return $this->styles[strtolower($name)]; + } + + /** + * {@inheritdoc} + */ + public function format(?string $message): ?string + { + return $this->formatAndWrap($message, 0); + } + + /** + * {@inheritdoc} + */ + public function formatAndWrap(?string $message, int $width) + { + if (null === $message) { + return ''; + } + + $offset = 0; + $output = ''; + $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*'; + $closeTagRegex = '[a-z][^<>]*+'; + $currentLineLength = 0; + preg_match_all("#<(($openTagRegex) | /($closeTagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); + foreach ($matches[0] as $i => $match) { + $pos = $match[1]; + $text = $match[0]; + + if (0 != $pos && '\\' == $message[$pos - 1]) { + continue; + } + + // add the text up to the next tag + $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); + $offset = $pos + \strlen($text); + + // opening tag? + if ($open = '/' != $text[1]) { + $tag = $matches[1][$i][0]; + } else { + $tag = $matches[3][$i][0] ?? ''; + } + + if (!$open && !$tag) { + // + $this->styleStack->pop(); + } elseif (null === $style = $this->createStyleFromString($tag)) { + $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); + } elseif ($open) { + $this->styleStack->push($style); + } else { + $this->styleStack->pop($style); + } + } + + $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); + + return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']); + } + + public function getStyleStack(): OutputFormatterStyleStack + { + return $this->styleStack; + } + + /** + * Tries to create new style instance from string. + */ + private function createStyleFromString(string $string): ?OutputFormatterStyleInterface + { + if (isset($this->styles[$string])) { + return $this->styles[$string]; + } + + if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) { + return null; + } + + $style = new OutputFormatterStyle(); + foreach ($matches as $match) { + array_shift($match); + $match[0] = strtolower($match[0]); + + if ('fg' == $match[0]) { + $style->setForeground(strtolower($match[1])); + } elseif ('bg' == $match[0]) { + $style->setBackground(strtolower($match[1])); + } elseif ('href' === $match[0]) { + $url = preg_replace('{\\\\([<>])}', '$1', $match[1]); + $style->setHref($url); + } elseif ('options' === $match[0]) { + preg_match_all('([^,;]+)', strtolower($match[1]), $options); + $options = array_shift($options); + foreach ($options as $option) { + $style->setOption($option); + } + } else { + return null; + } + } + + return $style; + } + + /** + * Applies current style from stack to text, if must be applied. + */ + private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string + { + if ('' === $text) { + return ''; + } + + if (!$width) { + return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text; + } + + if (!$currentLineLength && '' !== $current) { + $text = ltrim($text); + } + + if ($currentLineLength) { + $prefix = substr($text, 0, $i = $width - $currentLineLength)."\n"; + $text = substr($text, $i); + } else { + $prefix = ''; + } + + preg_match('~(\\n)$~', $text, $matches); + $text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text); + $text = rtrim($text, "\n").($matches[1] ?? ''); + + if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) { + $text = "\n".$text; + } + + $lines = explode("\n", $text); + + foreach ($lines as $line) { + $currentLineLength += \strlen($line); + if ($width <= $currentLineLength) { + $currentLineLength = 0; + } + } + + if ($this->isDecorated()) { + foreach ($lines as $i => $line) { + $lines[$i] = $this->styleStack->getCurrent()->apply($line); + } + } + + return implode("\n", $lines); + } +} diff --git a/cacme/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/cacme/vendor/symfony/console/Formatter/OutputFormatterInterface.php new file mode 100644 index 0000000..b94e51d --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/OutputFormatterInterface.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\Component\Console\Formatter; + +/** + * Formatter interface for console output. + * + * @author Konstantin Kudryashov + */ +interface OutputFormatterInterface +{ + /** + * Sets the decorated flag. + */ + public function setDecorated(bool $decorated); + + /** + * Whether the output will decorate messages. + */ + public function isDecorated(): bool; + + /** + * Sets a new style. + */ + public function setStyle(string $name, OutputFormatterStyleInterface $style); + + /** + * Checks if output formatter has style with specified name. + */ + public function hasStyle(string $name): bool; + + /** + * Gets style options from style with specified name. + * + * @throws \InvalidArgumentException When style isn't defined + */ + public function getStyle(string $name): OutputFormatterStyleInterface; + + /** + * Formats a message according to the given styles. + */ + public function format(?string $message): ?string; +} diff --git a/cacme/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/cacme/vendor/symfony/console/Formatter/OutputFormatterStyle.php new file mode 100644 index 0000000..0a009e9 --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/OutputFormatterStyle.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 Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Color; + +/** + * Formatter style class for defining styles. + * + * @author Konstantin Kudryashov + */ +class OutputFormatterStyle implements OutputFormatterStyleInterface +{ + private $color; + private string $foreground; + private string $background; + private array $options; + private ?string $href = null; + private bool $handlesHrefGracefully; + + /** + * Initializes output formatter style. + * + * @param string|null $foreground The style foreground color name + * @param string|null $background The style background color name + */ + public function __construct(string $foreground = null, string $background = null, array $options = []) + { + $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options); + } + + /** + * {@inheritdoc} + */ + public function setForeground(string $color = null) + { + $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options); + } + + /** + * {@inheritdoc} + */ + public function setBackground(string $color = null) + { + $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options); + } + + public function setHref(string $url): void + { + $this->href = $url; + } + + /** + * {@inheritdoc} + */ + public function setOption(string $option) + { + $this->options[] = $option; + $this->color = new Color($this->foreground, $this->background, $this->options); + } + + /** + * {@inheritdoc} + */ + public function unsetOption(string $option) + { + $pos = array_search($option, $this->options); + if (false !== $pos) { + unset($this->options[$pos]); + } + + $this->color = new Color($this->foreground, $this->background, $this->options); + } + + /** + * {@inheritdoc} + */ + public function setOptions(array $options) + { + $this->color = new Color($this->foreground, $this->background, $this->options = $options); + } + + /** + * {@inheritdoc} + */ + public function apply(string $text): string + { + $this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); + + if (null !== $this->href && $this->handlesHrefGracefully) { + $text = "\033]8;;$this->href\033\\$text\033]8;;\033\\"; + } + + return $this->color->apply($text); + } +} diff --git a/cacme/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/cacme/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php new file mode 100644 index 0000000..91d50aa --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.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\Component\Console\Formatter; + +/** + * Formatter style interface for defining styles. + * + * @author Konstantin Kudryashov + */ +interface OutputFormatterStyleInterface +{ + /** + * Sets style foreground color. + */ + public function setForeground(string $color = null); + + /** + * Sets style background color. + */ + public function setBackground(string $color = null); + + /** + * Sets some specific style option. + */ + public function setOption(string $option); + + /** + * Unsets some specific style option. + */ + public function unsetOption(string $option); + + /** + * Sets multiple style options at once. + */ + public function setOptions(array $options); + + /** + * Applies the style to a given text. + */ + public function apply(string $text): string; +} diff --git a/cacme/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/cacme/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php new file mode 100644 index 0000000..66f86a5 --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/OutputFormatterStyleStack.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 Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Contracts\Service\ResetInterface; + +/** + * @author Jean-François Simon + */ +class OutputFormatterStyleStack implements ResetInterface +{ + /** + * @var OutputFormatterStyleInterface[] + */ + private array $styles = []; + + private $emptyStyle; + + public function __construct(OutputFormatterStyleInterface $emptyStyle = null) + { + $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle(); + $this->reset(); + } + + /** + * Resets stack (ie. empty internal arrays). + */ + public function reset() + { + $this->styles = []; + } + + /** + * Pushes a style in the stack. + */ + public function push(OutputFormatterStyleInterface $style) + { + $this->styles[] = $style; + } + + /** + * Pops a style from the stack. + * + * @throws InvalidArgumentException When style tags incorrectly nested + */ + public function pop(OutputFormatterStyleInterface $style = null): OutputFormatterStyleInterface + { + if (empty($this->styles)) { + return $this->emptyStyle; + } + + if (null === $style) { + return array_pop($this->styles); + } + + foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { + if ($style->apply('') === $stackedStyle->apply('')) { + $this->styles = \array_slice($this->styles, 0, $index); + + return $stackedStyle; + } + } + + throw new InvalidArgumentException('Incorrectly nested style tag found.'); + } + + /** + * Computes current style with stacks top codes. + */ + public function getCurrent(): OutputFormatterStyleInterface + { + if (empty($this->styles)) { + return $this->emptyStyle; + } + + return $this->styles[\count($this->styles) - 1]; + } + + /** + * @return $this + */ + public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle): static + { + $this->emptyStyle = $emptyStyle; + + return $this; + } + + public function getEmptyStyle(): OutputFormatterStyleInterface + { + return $this->emptyStyle; + } +} diff --git a/cacme/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php b/cacme/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php new file mode 100644 index 0000000..42319ee --- /dev/null +++ b/cacme/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.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\Console\Formatter; + +/** + * Formatter interface for console output that supports word wrapping. + * + * @author Roland Franssen + */ +interface WrappableOutputFormatterInterface extends OutputFormatterInterface +{ + /** + * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). + */ + public function formatAndWrap(?string $message, int $width); +} diff --git a/cacme/vendor/symfony/console/Helper/DebugFormatterHelper.php b/cacme/vendor/symfony/console/Helper/DebugFormatterHelper.php new file mode 100644 index 0000000..64c7cff --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/DebugFormatterHelper.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\Component\Console\Helper; + +/** + * Helps outputting debug information when running an external program from a command. + * + * An external program can be a Process, an HTTP request, or anything else. + * + * @author Fabien Potencier + */ +class DebugFormatterHelper extends Helper +{ + private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; + private array $started = []; + private int $count = -1; + + /** + * Starts a debug formatting session. + */ + public function start(string $id, string $message, string $prefix = 'RUN'): string + { + $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)]; + + return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); + } + + /** + * Adds progress to a formatting session. + */ + public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR'): string + { + $message = ''; + + if ($error) { + if (isset($this->started[$id]['out'])) { + $message .= "\n"; + unset($this->started[$id]['out']); + } + if (!isset($this->started[$id]['err'])) { + $message .= sprintf('%s %s ', $this->getBorder($id), $errorPrefix); + $this->started[$id]['err'] = true; + } + + $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); + } else { + if (isset($this->started[$id]['err'])) { + $message .= "\n"; + unset($this->started[$id]['err']); + } + if (!isset($this->started[$id]['out'])) { + $message .= sprintf('%s %s ', $this->getBorder($id), $prefix); + $this->started[$id]['out'] = true; + } + + $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); + } + + return $message; + } + + /** + * Stops a formatting session. + */ + public function stop(string $id, string $message, bool $successful, string $prefix = 'RES'): string + { + $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; + + if ($successful) { + return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + } + + $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + + unset($this->started[$id]['out'], $this->started[$id]['err']); + + return $message; + } + + private function getBorder(string $id): string + { + return sprintf(' ', self::COLORS[$this->started[$id]['border']]); + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return 'debug_formatter'; + } +} diff --git a/cacme/vendor/symfony/console/Helper/DescriptorHelper.php b/cacme/vendor/symfony/console/Helper/DescriptorHelper.php new file mode 100644 index 0000000..63597c6 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/DescriptorHelper.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Descriptor\DescriptorInterface; +use Symfony\Component\Console\Descriptor\JsonDescriptor; +use Symfony\Component\Console\Descriptor\MarkdownDescriptor; +use Symfony\Component\Console\Descriptor\TextDescriptor; +use Symfony\Component\Console\Descriptor\XmlDescriptor; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * This class adds helper method to describe objects in various formats. + * + * @author Jean-François Simon + */ +class DescriptorHelper extends Helper +{ + /** + * @var DescriptorInterface[] + */ + private array $descriptors = []; + + public function __construct() + { + $this + ->register('txt', new TextDescriptor()) + ->register('xml', new XmlDescriptor()) + ->register('json', new JsonDescriptor()) + ->register('md', new MarkdownDescriptor()) + ; + } + + /** + * Describes an object if supported. + * + * Available options are: + * * format: string, the output format name + * * raw_text: boolean, sets output type as raw + * + * @throws InvalidArgumentException when the given format is not supported + */ + public function describe(OutputInterface $output, ?object $object, array $options = []) + { + $options = array_merge([ + 'raw_text' => false, + 'format' => 'txt', + ], $options); + + if (!isset($this->descriptors[$options['format']])) { + throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); + } + + $descriptor = $this->descriptors[$options['format']]; + $descriptor->describe($output, $object, $options); + } + + /** + * Registers a descriptor. + * + * @return $this + */ + public function register(string $format, DescriptorInterface $descriptor): static + { + $this->descriptors[$format] = $descriptor; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return 'descriptor'; + } + + public function getFormats(): array + { + return array_keys($this->descriptors); + } +} diff --git a/cacme/vendor/symfony/console/Helper/Dumper.php b/cacme/vendor/symfony/console/Helper/Dumper.php new file mode 100644 index 0000000..5019095 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/Dumper.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\Console\Helper; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Roland Franssen + */ +final class Dumper +{ + private $output; + private $dumper; + private $cloner; + private \Closure $handler; + + public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) + { + $this->output = $output; + $this->dumper = $dumper; + $this->cloner = $cloner; + + if (class_exists(CliDumper::class)) { + $this->handler = function ($var): string { + $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); + $dumper->setColors($this->output->isDecorated()); + + return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); + }; + } else { + $this->handler = function ($var): string { + switch (true) { + case null === $var: + return 'null'; + case true === $var: + return 'true'; + case false === $var: + return 'false'; + case \is_string($var): + return '"'.$var.'"'; + default: + return rtrim(print_r($var, true)); + } + }; + } + } + + public function __invoke(mixed $var): string + { + return ($this->handler)($var); + } +} diff --git a/cacme/vendor/symfony/console/Helper/FormatterHelper.php b/cacme/vendor/symfony/console/Helper/FormatterHelper.php new file mode 100644 index 0000000..2d7d1fa --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/FormatterHelper.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * The Formatter class provides helpers to format messages. + * + * @author Fabien Potencier + */ +class FormatterHelper extends Helper +{ + /** + * Formats a message within a section. + */ + public function formatSection(string $section, string $message, string $style = 'info'): string + { + return sprintf('<%s>[%s] %s', $style, $section, $style, $message); + } + + /** + * Formats a message as a block of text. + */ + public function formatBlock(string|array $messages, string $style, bool $large = false): string + { + if (!\is_array($messages)) { + $messages = [$messages]; + } + + $len = 0; + $lines = []; + foreach ($messages as $message) { + $message = OutputFormatter::escape($message); + $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); + $len = max(self::width($message) + ($large ? 4 : 2), $len); + } + + $messages = $large ? [str_repeat(' ', $len)] : []; + for ($i = 0; isset($lines[$i]); ++$i) { + $messages[] = $lines[$i].str_repeat(' ', $len - self::width($lines[$i])); + } + if ($large) { + $messages[] = str_repeat(' ', $len); + } + + for ($i = 0; isset($messages[$i]); ++$i) { + $messages[$i] = sprintf('<%s>%s', $style, $messages[$i], $style); + } + + return implode("\n", $messages); + } + + /** + * Truncates a message to the given length. + */ + public function truncate(string $message, int $length, string $suffix = '...'): string + { + $computedLength = $length - self::width($suffix); + + if ($computedLength > self::width($message)) { + return $message; + } + + return self::substr($message, 0, $length).$suffix; + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return 'formatter'; + } +} diff --git a/cacme/vendor/symfony/console/Helper/Helper.php b/cacme/vendor/symfony/console/Helper/Helper.php new file mode 100644 index 0000000..c626729 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/Helper.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\String\UnicodeString; + +/** + * Helper is the base class for all helper classes. + * + * @author Fabien Potencier + */ +abstract class Helper implements HelperInterface +{ + protected $helperSet = null; + + /** + * {@inheritdoc} + */ + public function setHelperSet(HelperSet $helperSet = null) + { + $this->helperSet = $helperSet; + } + + /** + * {@inheritdoc} + */ + public function getHelperSet(): ?HelperSet + { + return $this->helperSet; + } + + /** + * Returns the width of a string, using mb_strwidth if it is available. + * The width is how many characters positions the string will use. + */ + public static function width(?string $string): int + { + $string ?? $string = ''; + + if (preg_match('//u', $string)) { + return (new UnicodeString($string))->width(false); + } + + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return \strlen($string); + } + + return mb_strwidth($string, $encoding); + } + + /** + * Returns the length of a string, using mb_strlen if it is available. + * The length is related to how many bytes the string will use. + */ + public static function length(?string $string): int + { + $string ?? $string = ''; + + if (preg_match('//u', $string)) { + return (new UnicodeString($string))->length(); + } + + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return \strlen($string); + } + + return mb_strlen($string, $encoding); + } + + /** + * Returns the subset of a string, using mb_substr if it is available. + */ + public static function substr(?string $string, int $from, int $length = null): string + { + $string ?? $string = ''; + + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return substr($string, $from, $length); + } + + return mb_substr($string, $from, $length, $encoding); + } + + public static function formatTime(int|float $secs) + { + static $timeFormats = [ + [0, '< 1 sec'], + [1, '1 sec'], + [2, 'secs', 1], + [60, '1 min'], + [120, 'mins', 60], + [3600, '1 hr'], + [7200, 'hrs', 3600], + [86400, '1 day'], + [172800, 'days', 86400], + ]; + + foreach ($timeFormats as $index => $format) { + if ($secs >= $format[0]) { + if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0]) + || $index == \count($timeFormats) - 1 + ) { + if (2 == \count($format)) { + return $format[1]; + } + + return floor($secs / $format[2]).' '.$format[1]; + } + } + } + } + + public static function formatMemory(int $memory) + { + if ($memory >= 1024 * 1024 * 1024) { + return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); + } + + if ($memory >= 1024 * 1024) { + return sprintf('%.1f MiB', $memory / 1024 / 1024); + } + + if ($memory >= 1024) { + return sprintf('%d KiB', $memory / 1024); + } + + return sprintf('%d B', $memory); + } + + public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string) + { + $isDecorated = $formatter->isDecorated(); + $formatter->setDecorated(false); + // remove <...> formatting + $string = $formatter->format($string ?? ''); + // remove already formatted characters + $string = preg_replace("/\033\[[^m]*m/", '', $string ?? ''); + // remove terminal hyperlinks + $string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string ?? ''); + $formatter->setDecorated($isDecorated); + + return $string; + } +} diff --git a/cacme/vendor/symfony/console/Helper/HelperInterface.php b/cacme/vendor/symfony/console/Helper/HelperInterface.php new file mode 100644 index 0000000..1d2b7bf --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/HelperInterface.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\Console\Helper; + +/** + * HelperInterface is the interface all helpers must implement. + * + * @author Fabien Potencier + */ +interface HelperInterface +{ + /** + * Sets the helper set associated with this helper. + */ + public function setHelperSet(HelperSet $helperSet = null); + + /** + * Gets the helper set associated with this helper. + */ + public function getHelperSet(): ?HelperSet; + + /** + * Returns the canonical name of this helper. + * + * @return string + */ + public function getName(); +} diff --git a/cacme/vendor/symfony/console/Helper/HelperSet.php b/cacme/vendor/symfony/console/Helper/HelperSet.php new file mode 100644 index 0000000..be0beca --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/HelperSet.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * HelperSet represents a set of helpers to be used with a command. + * + * @author Fabien Potencier + * + * @implements \IteratorAggregate + */ +class HelperSet implements \IteratorAggregate +{ + /** @var array */ + private array $helpers = []; + + /** + * @param Helper[] $helpers An array of helper + */ + public function __construct(array $helpers = []) + { + foreach ($helpers as $alias => $helper) { + $this->set($helper, \is_int($alias) ? null : $alias); + } + } + + public function set(HelperInterface $helper, string $alias = null) + { + $this->helpers[$helper->getName()] = $helper; + if (null !== $alias) { + $this->helpers[$alias] = $helper; + } + + $helper->setHelperSet($this); + } + + /** + * Returns true if the helper if defined. + */ + public function has(string $name): bool + { + return isset($this->helpers[$name]); + } + + /** + * Gets a helper value. + * + * @throws InvalidArgumentException if the helper is not defined + */ + public function get(string $name): HelperInterface + { + if (!$this->has($name)) { + throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); + } + + return $this->helpers[$name]; + } + + public function getIterator(): \Traversable + { + return new \ArrayIterator($this->helpers); + } +} diff --git a/cacme/vendor/symfony/console/Helper/InputAwareHelper.php b/cacme/vendor/symfony/console/Helper/InputAwareHelper.php new file mode 100644 index 0000000..0d0dba2 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/InputAwareHelper.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Input\InputAwareInterface; +use Symfony\Component\Console\Input\InputInterface; + +/** + * An implementation of InputAwareInterface for Helpers. + * + * @author Wouter J + */ +abstract class InputAwareHelper extends Helper implements InputAwareInterface +{ + protected $input; + + /** + * {@inheritdoc} + */ + public function setInput(InputInterface $input) + { + $this->input = $input; + } +} diff --git a/cacme/vendor/symfony/console/Helper/ProcessHelper.php b/cacme/vendor/symfony/console/Helper/ProcessHelper.php new file mode 100644 index 0000000..e5ba4db --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/ProcessHelper.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Exception\ProcessFailedException; +use Symfony\Component\Process\Process; + +/** + * The ProcessHelper class provides helpers to run external processes. + * + * @author Fabien Potencier + * + * @final + */ +class ProcessHelper extends Helper +{ + /** + * Runs an external process. + * + * @param array|Process $cmd An instance of Process or an array of the command and arguments + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + */ + public function run(OutputInterface $output, array|Process $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process + { + if (!class_exists(Process::class)) { + throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); + } + + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $formatter = $this->getHelperSet()->get('debug_formatter'); + + if ($cmd instanceof Process) { + $cmd = [$cmd]; + } + + if (\is_string($cmd[0] ?? null)) { + $process = new Process($cmd); + $cmd = []; + } elseif (($cmd[0] ?? null) instanceof Process) { + $process = $cmd[0]; + unset($cmd[0]); + } else { + throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); + } + + if ($verbosity <= $output->getVerbosity()) { + $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine()))); + } + + if ($output->isDebug()) { + $callback = $this->wrapCallback($output, $process, $callback); + } + + $process->run($callback, $cmd); + + if ($verbosity <= $output->getVerbosity()) { + $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); + $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); + } + + if (!$process->isSuccessful() && null !== $error) { + $output->writeln(sprintf('%s', $this->escapeString($error))); + } + + return $process; + } + + /** + * Runs the process. + * + * This is identical to run() except that an exception is thrown if the process + * exits with a non-zero exit code. + * + * @param array|Process $cmd An instance of Process or a command to run + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @throws ProcessFailedException + * + * @see run() + */ + public function mustRun(OutputInterface $output, array|Process $cmd, string $error = null, callable $callback = null): Process + { + $process = $this->run($output, $cmd, $error, $callback); + + if (!$process->isSuccessful()) { + throw new ProcessFailedException($process); + } + + return $process; + } + + /** + * Wraps a Process callback to add debugging output. + */ + public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $formatter = $this->getHelperSet()->get('debug_formatter'); + + return function ($type, $buffer) use ($output, $process, $callback, $formatter) { + $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); + + if (null !== $callback) { + $callback($type, $buffer); + } + }; + } + + private function escapeString(string $str): string + { + return str_replace('<', '\\<', $str); + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return 'process'; + } +} diff --git a/cacme/vendor/symfony/console/Helper/ProgressBar.php b/cacme/vendor/symfony/console/Helper/ProgressBar.php new file mode 100644 index 0000000..2b4a45f --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/ProgressBar.php @@ -0,0 +1,603 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Cursor; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Terminal; + +/** + * The ProgressBar provides helpers to display progress output. + * + * @author Fabien Potencier + * @author Chris Jones + */ +final class ProgressBar +{ + public const FORMAT_VERBOSE = 'verbose'; + public const FORMAT_VERY_VERBOSE = 'very_verbose'; + public const FORMAT_DEBUG = 'debug'; + public const FORMAT_NORMAL = 'normal'; + + private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax'; + private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax'; + private const FORMAT_DEBUG_NOMAX = 'debug_nomax'; + private const FORMAT_NORMAL_NOMAX = 'normal_nomax'; + + private int $barWidth = 28; + private string $barChar; + private string $emptyBarChar = '-'; + private string $progressChar = '>'; + private ?string $format = null; + private ?string $internalFormat = null; + private ?int $redrawFreq = 1; + private int $writeCount = 0; + private float $lastWriteTime = 0; + private float $minSecondsBetweenRedraws = 0; + private float $maxSecondsBetweenRedraws = 1; + private $output; + private int $step = 0; + private ?int $max = null; + private int $startTime; + private int $stepWidth; + private float $percent = 0.0; + private array $messages = []; + private bool $overwrite = true; + private $terminal; + private ?string $previousMessage = null; + private $cursor; + + private static array $formatters; + private static array $formats; + + /** + * @param int $max Maximum steps (0 if unknown) + */ + public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $this->output = $output; + $this->setMaxSteps($max); + $this->terminal = new Terminal(); + + if (0 < $minSecondsBetweenRedraws) { + $this->redrawFreq = null; + $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; + } + + if (!$this->output->isDecorated()) { + // disable overwrite when output does not support ANSI codes. + $this->overwrite = false; + + // set a reasonable redraw frequency so output isn't flooded + $this->redrawFreq = null; + } + + $this->startTime = time(); + $this->cursor = new Cursor($output); + } + + /** + * Sets a placeholder formatter for a given name. + * + * This method also allow you to override an existing placeholder. + * + * @param string $name The placeholder name (including the delimiter char like %) + * @param callable $callable A PHP callable + */ + public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void + { + self::$formatters ??= self::initPlaceholderFormatters(); + + self::$formatters[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name. + * + * @param string $name The placeholder name (including the delimiter char like %) + */ + public static function getPlaceholderFormatterDefinition(string $name): ?callable + { + self::$formatters ??= self::initPlaceholderFormatters(); + + return self::$formatters[$name] ?? null; + } + + /** + * Sets a format for a given name. + * + * This method also allow you to override an existing format. + * + * @param string $name The format name + * @param string $format A format string + */ + public static function setFormatDefinition(string $name, string $format): void + { + self::$formats ??= self::initFormats(); + + self::$formats[$name] = $format; + } + + /** + * Gets the format for a given name. + * + * @param string $name The format name + */ + public static function getFormatDefinition(string $name): ?string + { + self::$formats ??= self::initFormats(); + + return self::$formats[$name] ?? null; + } + + /** + * Associates a text with a named placeholder. + * + * The text is displayed when the progress bar is rendered but only + * when the corresponding placeholder is part of the custom format line + * (by wrapping the name with %). + * + * @param string $message The text to associate with the placeholder + * @param string $name The name of the placeholder + */ + public function setMessage(string $message, string $name = 'message') + { + $this->messages[$name] = $message; + } + + public function getMessage(string $name = 'message') + { + return $this->messages[$name]; + } + + public function getStartTime(): int + { + return $this->startTime; + } + + public function getMaxSteps(): int + { + return $this->max; + } + + public function getProgress(): int + { + return $this->step; + } + + private function getStepWidth(): int + { + return $this->stepWidth; + } + + public function getProgressPercent(): float + { + return $this->percent; + } + + public function getBarOffset(): float + { + return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth); + } + + public function getEstimated(): float + { + if (!$this->step) { + return 0; + } + + return round((time() - $this->startTime) / $this->step * $this->max); + } + + public function getRemaining(): float + { + if (!$this->step) { + return 0; + } + + return round((time() - $this->startTime) / $this->step * ($this->max - $this->step)); + } + + public function setBarWidth(int $size) + { + $this->barWidth = max(1, $size); + } + + public function getBarWidth(): int + { + return $this->barWidth; + } + + public function setBarCharacter(string $char) + { + $this->barChar = $char; + } + + public function getBarCharacter(): string + { + return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar); + } + + public function setEmptyBarCharacter(string $char) + { + $this->emptyBarChar = $char; + } + + public function getEmptyBarCharacter(): string + { + return $this->emptyBarChar; + } + + public function setProgressCharacter(string $char) + { + $this->progressChar = $char; + } + + public function getProgressCharacter(): string + { + return $this->progressChar; + } + + public function setFormat(string $format) + { + $this->format = null; + $this->internalFormat = $format; + } + + /** + * Sets the redraw frequency. + * + * @param int|null $freq The frequency in steps + */ + public function setRedrawFrequency(?int $freq) + { + $this->redrawFreq = null !== $freq ? max(1, $freq) : null; + } + + public function minSecondsBetweenRedraws(float $seconds): void + { + $this->minSecondsBetweenRedraws = $seconds; + } + + public function maxSecondsBetweenRedraws(float $seconds): void + { + $this->maxSecondsBetweenRedraws = $seconds; + } + + /** + * Returns an iterator that will automatically update the progress bar when iterated. + * + * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable + */ + public function iterate(iterable $iterable, int $max = null): iterable + { + $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); + + foreach ($iterable as $key => $value) { + yield $key => $value; + + $this->advance(); + } + + $this->finish(); + } + + /** + * Starts the progress output. + * + * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged + */ + public function start(int $max = null) + { + $this->startTime = time(); + $this->step = 0; + $this->percent = 0.0; + + if (null !== $max) { + $this->setMaxSteps($max); + } + + $this->display(); + } + + /** + * Advances the progress output X steps. + * + * @param int $step Number of steps to advance + */ + public function advance(int $step = 1) + { + $this->setProgress($this->step + $step); + } + + /** + * Sets whether to overwrite the progressbar, false for new line. + */ + public function setOverwrite(bool $overwrite) + { + $this->overwrite = $overwrite; + } + + public function setProgress(int $step) + { + if ($this->max && $step > $this->max) { + $this->max = $step; + } elseif ($step < 0) { + $step = 0; + } + + $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); + $prevPeriod = (int) ($this->step / $redrawFreq); + $currPeriod = (int) ($step / $redrawFreq); + $this->step = $step; + $this->percent = $this->max ? (float) $this->step / $this->max : 0; + $timeInterval = microtime(true) - $this->lastWriteTime; + + // Draw regardless of other limits + if ($this->max === $step) { + $this->display(); + + return; + } + + // Throttling + if ($timeInterval < $this->minSecondsBetweenRedraws) { + return; + } + + // Draw each step period, but not too late + if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { + $this->display(); + } + } + + public function setMaxSteps(int $max) + { + $this->format = null; + $this->max = max(0, $max); + $this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4; + } + + /** + * Finishes the progress output. + */ + public function finish(): void + { + if (!$this->max) { + $this->max = $this->step; + } + + if ($this->step === $this->max && !$this->overwrite) { + // prevent double 100% output + return; + } + + $this->setProgress($this->max); + } + + /** + * Outputs the current progress string. + */ + public function display(): void + { + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; + } + + if (null === $this->format) { + $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); + } + + $this->overwrite($this->buildLine()); + } + + /** + * Removes the progress bar from the current line. + * + * This is useful if you wish to write some output + * while a progress bar is running. + * Call display() to show the progress bar again. + */ + public function clear(): void + { + if (!$this->overwrite) { + return; + } + + if (null === $this->format) { + $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); + } + + $this->overwrite(''); + } + + private function setRealFormat(string $format) + { + // try to use the _nomax variant if available + if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { + $this->format = self::getFormatDefinition($format.'_nomax'); + } elseif (null !== self::getFormatDefinition($format)) { + $this->format = self::getFormatDefinition($format); + } else { + $this->format = $format; + } + } + + /** + * Overwrites a previous message to the output. + */ + private function overwrite(string $message): void + { + if ($this->previousMessage === $message) { + return; + } + + $originalMessage = $message; + + if ($this->overwrite) { + if (null !== $this->previousMessage) { + if ($this->output instanceof ConsoleSectionOutput) { + $messageLines = explode("\n", $this->previousMessage); + $lineCount = \count($messageLines); + foreach ($messageLines as $messageLine) { + $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine)); + if ($messageLineLength > $this->terminal->getWidth()) { + $lineCount += floor($messageLineLength / $this->terminal->getWidth()); + } + } + $this->output->clear($lineCount); + } else { + $lineCount = substr_count($this->previousMessage, "\n"); + for ($i = 0; $i < $lineCount; ++$i) { + $this->cursor->moveToColumn(1); + $this->cursor->clearLine(); + $this->cursor->moveUp(); + } + + $this->cursor->moveToColumn(1); + $this->cursor->clearLine(); + } + } + } elseif ($this->step > 0) { + $message = \PHP_EOL.$message; + } + + $this->previousMessage = $originalMessage; + $this->lastWriteTime = microtime(true); + + $this->output->write($message); + ++$this->writeCount; + } + + private function determineBestFormat(): string + { + switch ($this->output->getVerbosity()) { + // OutputInterface::VERBOSITY_QUIET: display is disabled anyway + case OutputInterface::VERBOSITY_VERBOSE: + return $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + return $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX; + case OutputInterface::VERBOSITY_DEBUG: + return $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX; + default: + return $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX; + } + } + + private static function initPlaceholderFormatters(): array + { + return [ + 'bar' => function (self $bar, OutputInterface $output) { + $completeBars = $bar->getBarOffset(); + $display = str_repeat($bar->getBarCharacter(), $completeBars); + if ($completeBars < $bar->getBarWidth()) { + $emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter())); + $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars); + } + + return $display; + }, + 'elapsed' => function (self $bar) { + return Helper::formatTime(time() - $bar->getStartTime()); + }, + 'remaining' => function (self $bar) { + if (!$bar->getMaxSteps()) { + throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); + } + + return Helper::formatTime($bar->getRemaining()); + }, + 'estimated' => function (self $bar) { + if (!$bar->getMaxSteps()) { + throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); + } + + return Helper::formatTime($bar->getEstimated()); + }, + 'memory' => function (self $bar) { + return Helper::formatMemory(memory_get_usage(true)); + }, + 'current' => function (self $bar) { + return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT); + }, + 'max' => function (self $bar) { + return $bar->getMaxSteps(); + }, + 'percent' => function (self $bar) { + return floor($bar->getProgressPercent() * 100); + }, + ]; + } + + private static function initFormats(): array + { + return [ + self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%', + self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]', + + self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', + self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', + + self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', + self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', + + self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', + self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%', + ]; + } + + private function buildLine(): string + { + \assert(null !== $this->format); + + $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; + $callback = function ($matches) { + if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { + $text = $formatter($this, $this->output); + } elseif (isset($this->messages[$matches[1]])) { + $text = $this->messages[$matches[1]]; + } else { + return $matches[0]; + } + + if (isset($matches[2])) { + $text = sprintf('%'.$matches[2], $text); + } + + return $text; + }; + $line = preg_replace_callback($regex, $callback, $this->format); + + // gets string length for each sub line with multiline format + $linesLength = array_map(function ($subLine) { + return Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r"))); + }, explode("\n", $line)); + + $linesWidth = max($linesLength); + + $terminalWidth = $this->terminal->getWidth(); + if ($linesWidth <= $terminalWidth) { + return $line; + } + + $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); + + return preg_replace_callback($regex, $callback, $this->format); + } +} diff --git a/cacme/vendor/symfony/console/Helper/ProgressIndicator.php b/cacme/vendor/symfony/console/Helper/ProgressIndicator.php new file mode 100644 index 0000000..c746f9b --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/ProgressIndicator.php @@ -0,0 +1,244 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Kevin Bond + */ +class ProgressIndicator +{ + private const FORMATS = [ + 'normal' => ' %indicator% %message%', + 'normal_no_ansi' => ' %message%', + + 'verbose' => ' %indicator% %message% (%elapsed:6s%)', + 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', + + 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', + 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', + ]; + + private $output; + private int $startTime; + private ?string $format = null; + private ?string $message = null; + private array $indicatorValues; + private int $indicatorCurrent; + private int $indicatorChangeInterval; + private float $indicatorUpdateTime; + private bool $started = false; + + /** + * @var array + */ + private static array $formatters; + + /** + * @param int $indicatorChangeInterval Change interval in milliseconds + * @param array|null $indicatorValues Animated indicator characters + */ + public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) + { + $this->output = $output; + + if (null === $format) { + $format = $this->determineBestFormat(); + } + + if (null === $indicatorValues) { + $indicatorValues = ['-', '\\', '|', '/']; + } + + $indicatorValues = array_values($indicatorValues); + + if (2 > \count($indicatorValues)) { + throw new InvalidArgumentException('Must have at least 2 indicator value characters.'); + } + + $this->format = self::getFormatDefinition($format); + $this->indicatorChangeInterval = $indicatorChangeInterval; + $this->indicatorValues = $indicatorValues; + $this->startTime = time(); + } + + /** + * Sets the current indicator message. + */ + public function setMessage(?string $message) + { + $this->message = $message; + + $this->display(); + } + + /** + * Starts the indicator output. + */ + public function start(string $message) + { + if ($this->started) { + throw new LogicException('Progress indicator already started.'); + } + + $this->message = $message; + $this->started = true; + $this->startTime = time(); + $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; + $this->indicatorCurrent = 0; + + $this->display(); + } + + /** + * Advances the indicator. + */ + public function advance() + { + if (!$this->started) { + throw new LogicException('Progress indicator has not yet been started.'); + } + + if (!$this->output->isDecorated()) { + return; + } + + $currentTime = $this->getCurrentTimeInMilliseconds(); + + if ($currentTime < $this->indicatorUpdateTime) { + return; + } + + $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval; + ++$this->indicatorCurrent; + + $this->display(); + } + + /** + * Finish the indicator with message. + * + * @param $message + */ + public function finish(string $message) + { + if (!$this->started) { + throw new LogicException('Progress indicator has not yet been started.'); + } + + $this->message = $message; + $this->display(); + $this->output->writeln(''); + $this->started = false; + } + + /** + * Gets the format for a given name. + */ + public static function getFormatDefinition(string $name): ?string + { + return self::FORMATS[$name] ?? null; + } + + /** + * Sets a placeholder formatter for a given name. + * + * This method also allow you to override an existing placeholder. + */ + public static function setPlaceholderFormatterDefinition(string $name, callable $callable) + { + self::$formatters ??= self::initPlaceholderFormatters(); + + self::$formatters[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name (including the delimiter char like %). + */ + public static function getPlaceholderFormatterDefinition(string $name): ?callable + { + self::$formatters ??= self::initPlaceholderFormatters(); + + return self::$formatters[$name] ?? null; + } + + private function display() + { + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; + } + + $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { + if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { + return $formatter($this); + } + + return $matches[0]; + }, $this->format ?? '')); + } + + private function determineBestFormat(): string + { + switch ($this->output->getVerbosity()) { + // OutputInterface::VERBOSITY_QUIET: display is disabled anyway + case OutputInterface::VERBOSITY_VERBOSE: + return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi'; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + case OutputInterface::VERBOSITY_DEBUG: + return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi'; + default: + return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi'; + } + } + + /** + * Overwrites a previous message to the output. + */ + private function overwrite(string $message) + { + if ($this->output->isDecorated()) { + $this->output->write("\x0D\x1B[2K"); + $this->output->write($message); + } else { + $this->output->writeln($message); + } + } + + private function getCurrentTimeInMilliseconds(): float + { + return round(microtime(true) * 1000); + } + + /** + * @return array + */ + private static function initPlaceholderFormatters(): array + { + return [ + 'indicator' => function (self $indicator) { + return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; + }, + 'message' => function (self $indicator) { + return $indicator->message; + }, + 'elapsed' => function (self $indicator) { + return Helper::formatTime(time() - $indicator->startTime); + }, + 'memory' => function () { + return Helper::formatMemory(memory_get_usage(true)); + }, + ]; + } +} diff --git a/cacme/vendor/symfony/console/Helper/QuestionHelper.php b/cacme/vendor/symfony/console/Helper/QuestionHelper.php new file mode 100644 index 0000000..d53420b --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/QuestionHelper.php @@ -0,0 +1,598 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Cursor; +use Symfony\Component\Console\Exception\MissingInputException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\StreamableInputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +use function Symfony\Component\String\s; + +/** + * The QuestionHelper class provides helpers to interact with the user. + * + * @author Fabien Potencier + */ +class QuestionHelper extends Helper +{ + /** + * @var resource|null + */ + private $inputStream; + + private static bool $stty = true; + private static bool $stdinIsInteractive; + + /** + * Asks a question to the user. + * + * @return mixed The user answer + * + * @throws RuntimeException If there is no data to read in the input stream + */ + public function ask(InputInterface $input, OutputInterface $output, Question $question): mixed + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + if (!$input->isInteractive()) { + return $this->getDefaultAnswer($question); + } + + if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { + $this->inputStream = $stream; + } + + try { + if (!$question->getValidator()) { + return $this->doAsk($output, $question); + } + + $interviewer = function () use ($output, $question) { + return $this->doAsk($output, $question); + }; + + return $this->validateAttempts($interviewer, $output, $question); + } catch (MissingInputException $exception) { + $input->setInteractive(false); + + if (null === $fallbackOutput = $this->getDefaultAnswer($question)) { + throw $exception; + } + + return $fallbackOutput; + } + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return 'question'; + } + + /** + * Prevents usage of stty. + */ + public static function disableStty() + { + self::$stty = false; + } + + /** + * Asks the question to the user. + * + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden + */ + private function doAsk(OutputInterface $output, Question $question): mixed + { + $this->writePrompt($output, $question); + + $inputStream = $this->inputStream ?: \STDIN; + $autocomplete = $question->getAutocompleterCallback(); + + if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) { + $ret = false; + if ($question->isHidden()) { + try { + $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); + $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; + } catch (RuntimeException $e) { + if (!$question->isHiddenFallback()) { + throw $e; + } + } + } + + if (false === $ret) { + $ret = $this->readInput($inputStream, $question); + if (false === $ret) { + throw new MissingInputException('Aborted.'); + } + if ($question->isTrimmable()) { + $ret = trim($ret); + } + } + } else { + $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); + $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; + } + + if ($output instanceof ConsoleSectionOutput) { + $output->addContent($ret); + } + + $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); + + if ($normalizer = $question->getNormalizer()) { + return $normalizer($ret); + } + + return $ret; + } + + private function getDefaultAnswer(Question $question): mixed + { + $default = $question->getDefault(); + + if (null === $default) { + return $default; + } + + if ($validator = $question->getValidator()) { + return \call_user_func($question->getValidator(), $default); + } elseif ($question instanceof ChoiceQuestion) { + $choices = $question->getChoices(); + + if (!$question->isMultiselect()) { + return $choices[$default] ?? $default; + } + + $default = explode(',', $default); + foreach ($default as $k => $v) { + $v = $question->isTrimmable() ? trim($v) : $v; + $default[$k] = $choices[$v] ?? $v; + } + } + + return $default; + } + + /** + * Outputs the question prompt. + */ + protected function writePrompt(OutputInterface $output, Question $question) + { + $message = $question->getQuestion(); + + if ($question instanceof ChoiceQuestion) { + $output->writeln(array_merge([ + $question->getQuestion(), + ], $this->formatChoiceQuestionChoices($question, 'info'))); + + $message = $question->getPrompt(); + } + + $output->write($message); + } + + /** + * @return string[] + */ + protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag): array + { + $messages = []; + + $maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices()))); + + foreach ($choices as $key => $value) { + $padding = str_repeat(' ', $maxWidth - self::width($key)); + + $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); + } + + return $messages; + } + + /** + * Outputs an error message. + */ + protected function writeError(OutputInterface $output, \Exception $error) + { + if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { + $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); + } else { + $message = ''.$error->getMessage().''; + } + + $output->writeln($message); + } + + /** + * Autocompletes a question. + * + * @param resource $inputStream + */ + private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string + { + $cursor = new Cursor($output, $inputStream); + + $fullChoice = ''; + $ret = ''; + + $i = 0; + $ofs = -1; + $matches = $autocomplete($ret); + $numMatches = \count($matches); + + $sttyMode = shell_exec('stty -g'); + $isStdin = 'php://stdin' === (stream_get_meta_data($inputStream)['uri'] ?? null); + $r = [$inputStream]; + $w = []; + + // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) + shell_exec('stty -icanon -echo'); + + // Add highlighted text style + $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); + + // Read a keypress + while (!feof($inputStream)) { + while ($isStdin && 0 === @stream_select($r, $w, $w, 0, 100)) { + // Give signal handlers a chance to run + $r = [$inputStream]; + } + $c = fread($inputStream, 1); + + // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. + if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { + shell_exec('stty '.$sttyMode); + throw new MissingInputException('Aborted.'); + } elseif ("\177" === $c) { // Backspace Character + if (0 === $numMatches && 0 !== $i) { + --$i; + $cursor->moveLeft(s($fullChoice)->slice(-1)->width(false)); + + $fullChoice = self::substr($fullChoice, 0, $i); + } + + if (0 === $i) { + $ofs = -1; + $matches = $autocomplete($ret); + $numMatches = \count($matches); + } else { + $numMatches = 0; + } + + // Pop the last character off the end of our string + $ret = self::substr($ret, 0, $i); + } elseif ("\033" === $c) { + // Did we read an escape sequence? + $c .= fread($inputStream, 2); + + // A = Up Arrow. B = Down Arrow + if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { + if ('A' === $c[2] && -1 === $ofs) { + $ofs = 0; + } + + if (0 === $numMatches) { + continue; + } + + $ofs += ('A' === $c[2]) ? -1 : 1; + $ofs = ($numMatches + $ofs) % $numMatches; + } + } elseif (\ord($c) < 32) { + if ("\t" === $c || "\n" === $c) { + if ($numMatches > 0 && -1 !== $ofs) { + $ret = (string) $matches[$ofs]; + // Echo out remaining chars for current match + $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); + $output->write($remainingCharacters); + $fullChoice .= $remainingCharacters; + $i = (false === $encoding = mb_detect_encoding($fullChoice, null, true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding); + + $matches = array_filter( + $autocomplete($ret), + function ($match) use ($ret) { + return '' === $ret || str_starts_with($match, $ret); + } + ); + $numMatches = \count($matches); + $ofs = -1; + } + + if ("\n" === $c) { + $output->write($c); + break; + } + + $numMatches = 0; + } + + continue; + } else { + if ("\x80" <= $c) { + $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); + } + + $output->write($c); + $ret .= $c; + $fullChoice .= $c; + ++$i; + + $tempRet = $ret; + + if ($question instanceof ChoiceQuestion && $question->isMultiselect()) { + $tempRet = $this->mostRecentlyEnteredValue($fullChoice); + } + + $numMatches = 0; + $ofs = 0; + + foreach ($autocomplete($ret) as $value) { + // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) + if (str_starts_with($value, $tempRet)) { + $matches[$numMatches++] = $value; + } + } + } + + $cursor->clearLineAfter(); + + if ($numMatches > 0 && -1 !== $ofs) { + $cursor->savePosition(); + // Write highlighted text, complete the partially entered response + $charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))); + $output->write(''.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).''); + $cursor->restorePosition(); + } + } + + // Reset stty so it behaves normally again + shell_exec('stty '.$sttyMode); + + return $fullChoice; + } + + private function mostRecentlyEnteredValue(string $entered): string + { + // Determine the most recent value that the user entered + if (!str_contains($entered, ',')) { + return $entered; + } + + $choices = explode(',', $entered); + if ('' !== $lastChoice = trim($choices[\count($choices) - 1])) { + return $lastChoice; + } + + return $entered; + } + + /** + * Gets a hidden response from user. + * + * @param resource $inputStream The handler resource + * @param bool $trimmable Is the answer trimmable + * + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden + */ + private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string + { + if ('\\' === \DIRECTORY_SEPARATOR) { + $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; + + // handle code running from a phar + if ('phar:' === substr(__FILE__, 0, 5)) { + $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; + copy($exe, $tmpExe); + $exe = $tmpExe; + } + + $sExec = shell_exec('"'.$exe.'"'); + $value = $trimmable ? rtrim($sExec) : $sExec; + $output->writeln(''); + + if (isset($tmpExe)) { + unlink($tmpExe); + } + + return $value; + } + + if (self::$stty && Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); + shell_exec('stty -echo'); + } elseif ($this->isInteractiveInput($inputStream)) { + throw new RuntimeException('Unable to hide the response.'); + } + + $value = fgets($inputStream, 4096); + + if (self::$stty && Terminal::hasSttyAvailable()) { + shell_exec('stty '.$sttyMode); + } + + if (false === $value) { + throw new MissingInputException('Aborted.'); + } + if ($trimmable) { + $value = trim($value); + } + $output->writeln(''); + + return $value; + } + + /** + * Validates an attempt. + * + * @param callable $interviewer A callable that will ask for a question and return the result + * + * @throws \Exception In case the max number of attempts has been reached and no valid response has been given + */ + private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question): mixed + { + $error = null; + $attempts = $question->getMaxAttempts(); + + while (null === $attempts || $attempts--) { + if (null !== $error) { + $this->writeError($output, $error); + } + + try { + return $question->getValidator()($interviewer()); + } catch (RuntimeException $e) { + throw $e; + } catch (\Exception $error) { + } + } + + throw $error; + } + + private function isInteractiveInput($inputStream): bool + { + if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) { + return false; + } + + if (isset(self::$stdinIsInteractive)) { + return self::$stdinIsInteractive; + } + + if (\function_exists('stream_isatty')) { + return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); + } + + if (\function_exists('posix_isatty')) { + return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); + } + + if (!\function_exists('exec')) { + return self::$stdinIsInteractive = true; + } + + exec('stty 2> /dev/null', $output, $status); + + return self::$stdinIsInteractive = 1 !== $status; + } + + /** + * Reads one or more lines of input and returns what is read. + * + * @param resource $inputStream The handler resource + * @param Question $question The question being asked + */ + private function readInput($inputStream, Question $question): string|false + { + if (!$question->isMultiline()) { + $cp = $this->setIOCodepage(); + $ret = fgets($inputStream, 4096); + + return $this->resetIOCodepage($cp, $ret); + } + + $multiLineStreamReader = $this->cloneInputStream($inputStream); + if (null === $multiLineStreamReader) { + return false; + } + + $ret = ''; + $cp = $this->setIOCodepage(); + while (false !== ($char = fgetc($multiLineStreamReader))) { + if (\PHP_EOL === "{$ret}{$char}") { + break; + } + $ret .= $char; + } + + return $this->resetIOCodepage($cp, $ret); + } + + private function setIOCodepage(): int + { + if (\function_exists('sapi_windows_cp_set')) { + $cp = sapi_windows_cp_get(); + sapi_windows_cp_set(sapi_windows_cp_get('oem')); + + return $cp; + } + + return 0; + } + + /** + * Sets console I/O to the specified code page and converts the user input. + */ + private function resetIOCodepage(int $cp, string|false $input): string|false + { + if (0 !== $cp) { + sapi_windows_cp_set($cp); + + if (false !== $input && '' !== $input) { + $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input); + } + } + + return $input; + } + + /** + * Clones an input stream in order to act on one instance of the same + * stream without affecting the other instance. + * + * @param resource $inputStream The handler resource + * + * @return resource|null The cloned resource, null in case it could not be cloned + */ + private function cloneInputStream($inputStream) + { + $streamMetaData = stream_get_meta_data($inputStream); + $seekable = $streamMetaData['seekable'] ?? false; + $mode = $streamMetaData['mode'] ?? 'rb'; + $uri = $streamMetaData['uri'] ?? null; + + if (null === $uri) { + return null; + } + + $cloneStream = fopen($uri, $mode); + + // For seekable and writable streams, add all the same data to the + // cloned stream and then seek to the same offset. + if (true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'])) { + $offset = ftell($inputStream); + rewind($inputStream); + stream_copy_to_stream($inputStream, $cloneStream); + fseek($inputStream, $offset); + fseek($cloneStream, $offset); + } + + return $cloneStream; + } +} diff --git a/cacme/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/cacme/vendor/symfony/console/Helper/SymfonyQuestionHelper.php new file mode 100644 index 0000000..01f94ab --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/SymfonyQuestionHelper.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Symfony Style Guide compliant question helper. + * + * @author Kevin Bond + */ +class SymfonyQuestionHelper extends QuestionHelper +{ + /** + * {@inheritdoc} + */ + protected function writePrompt(OutputInterface $output, Question $question) + { + $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); + $default = $question->getDefault(); + + if ($question->isMultiline()) { + $text .= sprintf(' (press %s to continue)', $this->getEofShortcut()); + } + + switch (true) { + case null === $default: + $text = sprintf(' %s:', $text); + + break; + + case $question instanceof ConfirmationQuestion: + $text = sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); + + break; + + case $question instanceof ChoiceQuestion && $question->isMultiselect(): + $choices = $question->getChoices(); + $default = explode(',', $default); + + foreach ($default as $key => $value) { + $default[$key] = $choices[trim($value)]; + } + + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); + + break; + + case $question instanceof ChoiceQuestion: + $choices = $question->getChoices(); + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($choices[$default] ?? $default)); + + break; + + default: + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); + } + + $output->writeln($text); + + $prompt = ' > '; + + if ($question instanceof ChoiceQuestion) { + $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); + + $prompt = $question->getPrompt(); + } + + $output->write($prompt); + } + + /** + * {@inheritdoc} + */ + protected function writeError(OutputInterface $output, \Exception $error) + { + if ($output instanceof SymfonyStyle) { + $output->newLine(); + $output->error($error->getMessage()); + + return; + } + + parent::writeError($output, $error); + } + + private function getEofShortcut(): string + { + if ('Windows' === \PHP_OS_FAMILY) { + return 'Ctrl+Z then Enter'; + } + + return 'Ctrl+D'; + } +} diff --git a/cacme/vendor/symfony/console/Helper/Table.php b/cacme/vendor/symfony/console/Helper/Table.php new file mode 100644 index 0000000..0d8da6c --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/Table.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 Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Provides helpers to display a table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + * @author Abdellatif Ait boudad + * @author Max Grigorian + * @author Dany Maillard + */ +class Table +{ + private const SEPARATOR_TOP = 0; + private const SEPARATOR_TOP_BOTTOM = 1; + private const SEPARATOR_MID = 2; + private const SEPARATOR_BOTTOM = 3; + private const BORDER_OUTSIDE = 0; + private const BORDER_INSIDE = 1; + + private ?string $headerTitle = null; + private ?string $footerTitle = null; + private array $headers = []; + private array $rows = []; + private bool $horizontal = false; + private array $effectiveColumnWidths = []; + private int $numberOfColumns; + private $output; + private $style; + private array $columnStyles = []; + private array $columnWidths = []; + private array $columnMaxWidths = []; + private bool $rendered = false; + + private static array $styles; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + + self::$styles ??= self::initStyles(); + + $this->setStyle('default'); + } + + /** + * Sets a style definition. + */ + public static function setStyleDefinition(string $name, TableStyle $style) + { + self::$styles ??= self::initStyles(); + + self::$styles[$name] = $style; + } + + /** + * Gets a style definition by name. + */ + public static function getStyleDefinition(string $name): TableStyle + { + self::$styles ??= self::initStyles(); + + return self::$styles[$name] ?? throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } + + /** + * Sets table style. + * + * @return $this + */ + public function setStyle(TableStyle|string $name): static + { + $this->style = $this->resolveStyle($name); + + return $this; + } + + /** + * Gets the current table style. + */ + public function getStyle(): TableStyle + { + return $this->style; + } + + /** + * Sets table column style. + * + * @param TableStyle|string $name The style name or a TableStyle instance + * + * @return $this + */ + public function setColumnStyle(int $columnIndex, TableStyle|string $name): static + { + $this->columnStyles[$columnIndex] = $this->resolveStyle($name); + + return $this; + } + + /** + * Gets the current style for a column. + * + * If style was not set, it returns the global table style. + */ + public function getColumnStyle(int $columnIndex): TableStyle + { + return $this->columnStyles[$columnIndex] ?? $this->getStyle(); + } + + /** + * Sets the minimum width of a column. + * + * @return $this + */ + public function setColumnWidth(int $columnIndex, int $width): static + { + $this->columnWidths[$columnIndex] = $width; + + return $this; + } + + /** + * Sets the minimum width of all columns. + * + * @return $this + */ + public function setColumnWidths(array $widths): static + { + $this->columnWidths = []; + foreach ($widths as $index => $width) { + $this->setColumnWidth($index, $width); + } + + return $this; + } + + /** + * Sets the maximum width of a column. + * + * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while + * formatted strings are preserved. + * + * @return $this + */ + public function setColumnMaxWidth(int $columnIndex, int $width): static + { + if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { + throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter()))); + } + + $this->columnMaxWidths[$columnIndex] = $width; + + return $this; + } + + /** + * @return $this + */ + public function setHeaders(array $headers): static + { + $headers = array_values($headers); + if (!empty($headers) && !\is_array($headers[0])) { + $headers = [$headers]; + } + + $this->headers = $headers; + + return $this; + } + + public function setRows(array $rows) + { + $this->rows = []; + + return $this->addRows($rows); + } + + /** + * @return $this + */ + public function addRows(array $rows): static + { + foreach ($rows as $row) { + $this->addRow($row); + } + + return $this; + } + + /** + * @return $this + */ + public function addRow(TableSeparator|array $row): static + { + if ($row instanceof TableSeparator) { + $this->rows[] = $row; + + return $this; + } + + $this->rows[] = array_values($row); + + return $this; + } + + /** + * Adds a row to the table, and re-renders the table. + * + * @return $this + */ + public function appendRow(TableSeparator|array $row): static + { + if (!$this->output instanceof ConsoleSectionOutput) { + throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); + } + + if ($this->rendered) { + $this->output->clear($this->calculateRowCount()); + } + + $this->addRow($row); + $this->render(); + + return $this; + } + + /** + * @return $this + */ + public function setRow(int|string $column, array $row): static + { + $this->rows[$column] = $row; + + return $this; + } + + /** + * @return $this + */ + public function setHeaderTitle(?string $title): static + { + $this->headerTitle = $title; + + return $this; + } + + /** + * @return $this + */ + public function setFooterTitle(?string $title): static + { + $this->footerTitle = $title; + + return $this; + } + + /** + * @return $this + */ + public function setHorizontal(bool $horizontal = true): static + { + $this->horizontal = $horizontal; + + return $this; + } + + /** + * Renders table to output. + * + * Example: + * + * +---------------+-----------------------+------------------+ + * | ISBN | Title | Author | + * +---------------+-----------------------+------------------+ + * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + * +---------------+-----------------------+------------------+ + */ + public function render() + { + $divider = new TableSeparator(); + if ($this->horizontal) { + $rows = []; + foreach ($this->headers[0] ?? [] as $i => $header) { + $rows[$i] = [$header]; + foreach ($this->rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + if (isset($row[$i])) { + $rows[$i][] = $row[$i]; + } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { + // Noop, there is a "title" + } else { + $rows[$i][] = null; + } + } + } + } else { + $rows = array_merge($this->headers, [$divider], $this->rows); + } + + $this->calculateNumberOfColumns($rows); + + $rowGroups = $this->buildTableRows($rows); + $this->calculateColumnsWidth($rowGroups); + + $isHeader = !$this->horizontal; + $isFirstRow = $this->horizontal; + $hasTitle = (bool) $this->headerTitle; + + foreach ($rowGroups as $rowGroup) { + $isHeaderSeparatorRendered = false; + + foreach ($rowGroup as $row) { + if ($divider === $row) { + $isHeader = false; + $isFirstRow = true; + + continue; + } + + if ($row instanceof TableSeparator) { + $this->renderRowSeparator(); + + continue; + } + + if (!$row) { + continue; + } + + if ($isHeader && !$isHeaderSeparatorRendered) { + $this->renderRowSeparator( + $isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, + $hasTitle ? $this->headerTitle : null, + $hasTitle ? $this->style->getHeaderTitleFormat() : null + ); + $hasTitle = false; + $isHeaderSeparatorRendered = true; + } + + if ($isFirstRow) { + $this->renderRowSeparator( + $isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, + $hasTitle ? $this->headerTitle : null, + $hasTitle ? $this->style->getHeaderTitleFormat() : null + ); + $isFirstRow = false; + $hasTitle = false; + } + + if ($this->horizontal) { + $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); + } else { + $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); + } + } + } + $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); + + $this->cleanup(); + $this->rendered = true; + } + + /** + * Renders horizontal header separator. + * + * Example: + * + * +-----+-----------+-------+ + */ + private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) + { + if (0 === $count = $this->numberOfColumns) { + return; + } + + $borders = $this->style->getBorderChars(); + if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) { + return; + } + + $crossings = $this->style->getCrossingChars(); + if (self::SEPARATOR_MID === $type) { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; + } elseif (self::SEPARATOR_TOP === $type) { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; + } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; + } else { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; + } + + $markup = $leftChar; + for ($column = 0; $column < $count; ++$column) { + $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]); + $markup .= $column === $count - 1 ? $rightChar : $midChar; + } + + if (null !== $title) { + $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title))); + $markupLength = Helper::width($markup); + if ($titleLength > $limit = $markupLength - 4) { + $titleLength = $limit; + $formatLength = Helper::width(Helper::removeDecoration($formatter, sprintf($titleFormat, ''))); + $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); + } + + $titleStart = intdiv($markupLength - $titleLength, 2); + if (false === mb_detect_encoding($markup, null, true)) { + $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength); + } else { + $markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength); + } + } + + $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); + } + + /** + * Renders vertical column separator. + */ + private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string + { + $borders = $this->style->getBorderChars(); + + return sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); + } + + /** + * Renders table row. + * + * Example: + * + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + */ + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) + { + $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); + $columns = $this->getRowColumns($row); + $last = \count($columns) - 1; + foreach ($columns as $i => $column) { + if ($firstCellFormat && 0 === $i) { + $rowContent .= $this->renderCell($row, $column, $firstCellFormat); + } else { + $rowContent .= $this->renderCell($row, $column, $cellFormat); + } + $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); + } + $this->output->writeln($rowContent); + } + + /** + * Renders table cell with padding. + */ + private function renderCell(array $row, int $column, string $cellFormat): string + { + $cell = $row[$column] ?? ''; + $width = $this->effectiveColumnWidths[$column]; + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + // add the width of the following columns(numbers of colspan). + foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { + $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn]; + } + } + + // str_pad won't work properly with multi-byte strings, we need to fix the padding + if (false !== $encoding = mb_detect_encoding($cell, null, true)) { + $width += \strlen($cell) - mb_strwidth($cell, $encoding); + } + + $style = $this->getColumnStyle($column); + + if ($cell instanceof TableSeparator) { + return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); + } + + $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell)); + $content = sprintf($style->getCellRowContentFormat(), $cell); + + $padType = $style->getPadType(); + if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) { + $isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell); + if ($isNotStyledByTag) { + $cellFormat = $cell->getStyle()->getCellFormat(); + if (!\is_string($cellFormat)) { + $tag = http_build_query($cell->getStyle()->getTagOptions(), '', ';'); + $cellFormat = '<'.$tag.'>%s'; + } + + if (strstr($content, '')) { + $content = str_replace('', '', $content); + $width -= 3; + } + if (strstr($content, '')) { + $content = str_replace('', '', $content); + $width -= \strlen(''); + } + } + + $padType = $cell->getStyle()->getPadByAlign(); + } + + return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType)); + } + + /** + * Calculate number of columns for this table. + */ + private function calculateNumberOfColumns(array $rows) + { + $columns = [0]; + foreach ($rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + + $columns[] = $this->getNumberOfColumns($row); + } + + $this->numberOfColumns = max($columns); + } + + private function buildTableRows(array $rows): TableRows + { + /** @var WrappableOutputFormatterInterface $formatter */ + $formatter = $this->output->getFormatter(); + $unmergedRows = []; + for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { + $rows = $this->fillNextRows($rows, $rowKey); + + // Remove any new line breaks and replace it with a new line + foreach ($rows[$rowKey] as $column => $cell) { + $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1; + + if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) { + $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); + } + if (!strstr($cell ?? '', "\n")) { + continue; + } + $escaped = implode("\n", array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode("\n", $cell))); + $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; + $lines = explode("\n", str_replace("\n", "\n", $cell)); + foreach ($lines as $lineKey => $line) { + if ($colspan > 1) { + $line = new TableCell($line, ['colspan' => $colspan]); + } + if (0 === $lineKey) { + $rows[$rowKey][$column] = $line; + } else { + if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) { + $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey); + } + $unmergedRows[$rowKey][$lineKey][$column] = $line; + } + } + } + } + + return new TableRows(function () use ($rows, $unmergedRows): \Traversable { + foreach ($rows as $rowKey => $row) { + $rowGroup = [$row instanceof TableSeparator ? $row : $this->fillCells($row)]; + + if (isset($unmergedRows[$rowKey])) { + foreach ($unmergedRows[$rowKey] as $row) { + $rowGroup[] = $row instanceof TableSeparator ? $row : $this->fillCells($row); + } + } + yield $rowGroup; + } + }); + } + + private function calculateRowCount(): int + { + $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows)))); + + if ($this->headers) { + ++$numberOfRows; // Add row for header separator + } + + if (\count($this->rows) > 0) { + ++$numberOfRows; // Add row for footer separator + } + + return $numberOfRows; + } + + /** + * fill rows that contains rowspan > 1. + * + * @throws InvalidArgumentException + */ + private function fillNextRows(array $rows, int $line): array + { + $unmergedRows = []; + foreach ($rows[$line] as $column => $cell) { + if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !$cell instanceof \Stringable) { + throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell))); + } + if ($cell instanceof TableCell && $cell->getRowspan() > 1) { + $nbLines = $cell->getRowspan() - 1; + $lines = [$cell]; + if (strstr($cell, "\n")) { + $lines = explode("\n", str_replace("\n", "\n", $cell)); + $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; + + $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); + unset($lines[0]); + } + + // create a two dimensional array (rowspan x colspan) + $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); + foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { + $value = $lines[$unmergedRowKey - $line] ?? ''; + $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); + if ($nbLines === $unmergedRowKey - $line) { + break; + } + } + } + } + + foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { + // we need to know if $unmergedRow will be merged or inserted into $rows + if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { + foreach ($unmergedRow as $cellKey => $cell) { + // insert cell into row at cellKey position + array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); + } + } else { + $row = $this->copyRow($rows, $unmergedRowKey - 1); + foreach ($unmergedRow as $column => $cell) { + if (!empty($cell)) { + $row[$column] = $unmergedRow[$column]; + } + } + array_splice($rows, $unmergedRowKey, 0, [$row]); + } + } + + return $rows; + } + + /** + * fill cells for a row that contains colspan > 1. + */ + private function fillCells(iterable $row) + { + $newRow = []; + + foreach ($row as $column => $cell) { + $newRow[] = $cell; + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) { + // insert empty value at column position + $newRow[] = ''; + } + } + } + + return $newRow ?: $row; + } + + private function copyRow(array $rows, int $line): array + { + $row = $rows[$line]; + foreach ($row as $cellKey => $cellValue) { + $row[$cellKey] = ''; + if ($cellValue instanceof TableCell) { + $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]); + } + } + + return $row; + } + + /** + * Gets number of columns by row. + */ + private function getNumberOfColumns(array $row): int + { + $columns = \count($row); + foreach ($row as $column) { + $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0; + } + + return $columns; + } + + /** + * Gets list of columns for the given row. + */ + private function getRowColumns(array $row): array + { + $columns = range(0, $this->numberOfColumns - 1); + foreach ($row as $cellKey => $cell) { + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + // exclude grouped columns. + $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1)); + } + } + + return $columns; + } + + /** + * Calculates columns widths. + */ + private function calculateColumnsWidth(iterable $groups) + { + for ($column = 0; $column < $this->numberOfColumns; ++$column) { + $lengths = []; + foreach ($groups as $group) { + foreach ($group as $row) { + if ($row instanceof TableSeparator) { + continue; + } + + foreach ($row as $i => $cell) { + if ($cell instanceof TableCell) { + $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); + $textLength = Helper::width($textContent); + if ($textLength > 0) { + $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); + foreach ($contentColumns as $position => $content) { + $row[$i + $position] = $content; + } + } + } + } + + $lengths[] = $this->getCellWidth($row, $column); + } + } + + $this->effectiveColumnWidths[$column] = max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2; + } + } + + private function getColumnSeparatorWidth(): int + { + return Helper::width(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); + } + + private function getCellWidth(array $row, int $column): int + { + $cellWidth = 0; + + if (isset($row[$column])) { + $cell = $row[$column]; + $cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell)); + } + + $columnWidth = $this->columnWidths[$column] ?? 0; + $cellWidth = max($cellWidth, $columnWidth); + + return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; + } + + /** + * Called after rendering to cleanup cache data. + */ + private function cleanup() + { + $this->effectiveColumnWidths = []; + unset($this->numberOfColumns); + } + + /** + * @return array + */ + private static function initStyles(): array + { + $borderless = new TableStyle(); + $borderless + ->setHorizontalBorderChars('=') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar(' ') + ; + + $compact = new TableStyle(); + $compact + ->setHorizontalBorderChars('') + ->setVerticalBorderChars('') + ->setDefaultCrossingChar('') + ->setCellRowContentFormat('%s ') + ; + + $styleGuide = new TableStyle(); + $styleGuide + ->setHorizontalBorderChars('-') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar(' ') + ->setCellHeaderFormat('%s') + ; + + $box = (new TableStyle()) + ->setHorizontalBorderChars('─') + ->setVerticalBorderChars('│') + ->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├') + ; + + $boxDouble = (new TableStyle()) + ->setHorizontalBorderChars('═', '─') + ->setVerticalBorderChars('║', '│') + ->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣') + ; + + return [ + 'default' => new TableStyle(), + 'borderless' => $borderless, + 'compact' => $compact, + 'symfony-style-guide' => $styleGuide, + 'box' => $box, + 'box-double' => $boxDouble, + ]; + } + + private function resolveStyle(TableStyle|string $name): TableStyle + { + if ($name instanceof TableStyle) { + return $name; + } + + return self::$styles[$name] ?? throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } +} diff --git a/cacme/vendor/symfony/console/Helper/TableCell.php b/cacme/vendor/symfony/console/Helper/TableCell.php new file mode 100644 index 0000000..394b2bc --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/TableCell.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\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Abdellatif Ait boudad + */ +class TableCell +{ + private string $value; + private array $options = [ + 'rowspan' => 1, + 'colspan' => 1, + 'style' => null, + ]; + + public function __construct(string $value = '', array $options = []) + { + $this->value = $value; + + // check option names + if ($diff = array_diff(array_keys($options), array_keys($this->options))) { + throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); + } + + if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) { + throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".'); + } + + $this->options = array_merge($this->options, $options); + } + + /** + * Returns the cell value. + */ + public function __toString(): string + { + return $this->value; + } + + /** + * Gets number of colspan. + */ + public function getColspan(): int + { + return (int) $this->options['colspan']; + } + + /** + * Gets number of rowspan. + */ + public function getRowspan(): int + { + return (int) $this->options['rowspan']; + } + + public function getStyle(): ?TableCellStyle + { + return $this->options['style']; + } +} diff --git a/cacme/vendor/symfony/console/Helper/TableCellStyle.php b/cacme/vendor/symfony/console/Helper/TableCellStyle.php new file mode 100644 index 0000000..65ae9e7 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/TableCellStyle.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\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Yewhen Khoptynskyi + */ +class TableCellStyle +{ + public const DEFAULT_ALIGN = 'left'; + + private const TAG_OPTIONS = [ + 'fg', + 'bg', + 'options', + ]; + + private const ALIGN_MAP = [ + 'left' => \STR_PAD_RIGHT, + 'center' => \STR_PAD_BOTH, + 'right' => \STR_PAD_LEFT, + ]; + + private array $options = [ + 'fg' => 'default', + 'bg' => 'default', + 'options' => null, + 'align' => self::DEFAULT_ALIGN, + 'cellFormat' => null, + ]; + + public function __construct(array $options = []) + { + if ($diff = array_diff(array_keys($options), array_keys($this->options))) { + throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff))); + } + + if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) { + throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP)))); + } + + $this->options = array_merge($this->options, $options); + } + + public function getOptions(): array + { + return $this->options; + } + + /** + * Gets options we need for tag for example fg, bg. + * + * @return string[] + */ + public function getTagOptions(): array + { + return array_filter( + $this->getOptions(), + function ($key) { + return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]); + }, + \ARRAY_FILTER_USE_KEY + ); + } + + public function getPadByAlign(): int + { + return self::ALIGN_MAP[$this->getOptions()['align']]; + } + + public function getCellFormat(): ?string + { + return $this->getOptions()['cellFormat']; + } +} diff --git a/cacme/vendor/symfony/console/Helper/TableRows.php b/cacme/vendor/symfony/console/Helper/TableRows.php new file mode 100644 index 0000000..97d0772 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/TableRows.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\Console\Helper; + +/** + * @internal + */ +class TableRows implements \IteratorAggregate +{ + private \Closure $generator; + + public function __construct(\Closure $generator) + { + $this->generator = $generator; + } + + public function getIterator(): \Traversable + { + return ($this->generator)(); + } +} diff --git a/cacme/vendor/symfony/console/Helper/TableSeparator.php b/cacme/vendor/symfony/console/Helper/TableSeparator.php new file mode 100644 index 0000000..e541c53 --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/TableSeparator.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\Console\Helper; + +/** + * Marks a row as being a separator. + * + * @author Fabien Potencier + */ +class TableSeparator extends TableCell +{ + public function __construct(array $options = []) + { + parent::__construct('', $options); + } +} diff --git a/cacme/vendor/symfony/console/Helper/TableStyle.php b/cacme/vendor/symfony/console/Helper/TableStyle.php new file mode 100644 index 0000000..bbad98e --- /dev/null +++ b/cacme/vendor/symfony/console/Helper/TableStyle.php @@ -0,0 +1,362 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Defines the styles for a Table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + * @author Dany Maillard + */ +class TableStyle +{ + private string $paddingChar = ' '; + private string $horizontalOutsideBorderChar = '-'; + private string $horizontalInsideBorderChar = '-'; + private string $verticalOutsideBorderChar = '|'; + private string $verticalInsideBorderChar = '|'; + private string $crossingChar = '+'; + private string $crossingTopRightChar = '+'; + private string $crossingTopMidChar = '+'; + private string $crossingTopLeftChar = '+'; + private string $crossingMidRightChar = '+'; + private string $crossingBottomRightChar = '+'; + private string $crossingBottomMidChar = '+'; + private string $crossingBottomLeftChar = '+'; + private string $crossingMidLeftChar = '+'; + private string $crossingTopLeftBottomChar = '+'; + private string $crossingTopMidBottomChar = '+'; + private string $crossingTopRightBottomChar = '+'; + private string $headerTitleFormat = ' %s '; + private string $footerTitleFormat = ' %s '; + private string $cellHeaderFormat = '%s'; + private string $cellRowFormat = '%s'; + private string $cellRowContentFormat = ' %s '; + private string $borderFormat = '%s'; + private int $padType = \STR_PAD_RIGHT; + + /** + * Sets padding character, used for cell padding. + * + * @return $this + */ + public function setPaddingChar(string $paddingChar): static + { + if (!$paddingChar) { + throw new LogicException('The padding char must not be empty.'); + } + + $this->paddingChar = $paddingChar; + + return $this; + } + + /** + * Gets padding character, used for cell padding. + */ + public function getPaddingChar(): string + { + return $this->paddingChar; + } + + /** + * Sets horizontal border characters. + * + * + * ╔═══════════════╤══════════════════════════╤══════════════════╗ + * 1 ISBN 2 Title │ Author ║ + * ╠═══════════════╪══════════════════════════╪══════════════════╣ + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * ╚═══════════════╧══════════════════════════╧══════════════════╝ + * + * + * @return $this + */ + public function setHorizontalBorderChars(string $outside, string $inside = null): static + { + $this->horizontalOutsideBorderChar = $outside; + $this->horizontalInsideBorderChar = $inside ?? $outside; + + return $this; + } + + /** + * Sets vertical border characters. + * + * + * ╔═══════════════╤══════════════════════════╤══════════════════╗ + * ║ ISBN │ Title │ Author ║ + * ╠═══════1═══════╪══════════════════════════╪══════════════════╣ + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * ╟───────2───────┼──────────────────────────┼──────────────────╢ + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * ╚═══════════════╧══════════════════════════╧══════════════════╝ + * + * + * @return $this + */ + public function setVerticalBorderChars(string $outside, string $inside = null): static + { + $this->verticalOutsideBorderChar = $outside; + $this->verticalInsideBorderChar = $inside ?? $outside; + + return $this; + } + + /** + * Gets border characters. + * + * @internal + */ + public function getBorderChars(): array + { + return [ + $this->horizontalOutsideBorderChar, + $this->verticalOutsideBorderChar, + $this->horizontalInsideBorderChar, + $this->verticalInsideBorderChar, + ]; + } + + /** + * Sets crossing characters. + * + * Example: + * + * 1═══════════════2══════════════════════════2══════════════════3 + * ║ ISBN │ Title │ Author ║ + * 8'══════════════0'═════════════════════════0'═════════════════4' + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * 8───────────────0──────────────────────────0──────────────────4 + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * 7═══════════════6══════════════════════════6══════════════════5 + * + * + * @param string $cross Crossing char (see #0 of example) + * @param string $topLeft Top left char (see #1 of example) + * @param string $topMid Top mid char (see #2 of example) + * @param string $topRight Top right char (see #3 of example) + * @param string $midRight Mid right char (see #4 of example) + * @param string $bottomRight Bottom right char (see #5 of example) + * @param string $bottomMid Bottom mid char (see #6 of example) + * @param string $bottomLeft Bottom left char (see #7 of example) + * @param string $midLeft Mid left char (see #8 of example) + * @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null + * @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null + * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null + * + * @return $this + */ + public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): static + { + $this->crossingChar = $cross; + $this->crossingTopLeftChar = $topLeft; + $this->crossingTopMidChar = $topMid; + $this->crossingTopRightChar = $topRight; + $this->crossingMidRightChar = $midRight; + $this->crossingBottomRightChar = $bottomRight; + $this->crossingBottomMidChar = $bottomMid; + $this->crossingBottomLeftChar = $bottomLeft; + $this->crossingMidLeftChar = $midLeft; + $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; + $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; + $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; + + return $this; + } + + /** + * Sets default crossing character used for each cross. + * + * @see {@link setCrossingChars()} for setting each crossing individually. + */ + public function setDefaultCrossingChar(string $char): self + { + return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); + } + + /** + * Gets crossing character. + */ + public function getCrossingChar(): string + { + return $this->crossingChar; + } + + /** + * Gets crossing characters. + * + * @internal + */ + public function getCrossingChars(): array + { + return [ + $this->crossingChar, + $this->crossingTopLeftChar, + $this->crossingTopMidChar, + $this->crossingTopRightChar, + $this->crossingMidRightChar, + $this->crossingBottomRightChar, + $this->crossingBottomMidChar, + $this->crossingBottomLeftChar, + $this->crossingMidLeftChar, + $this->crossingTopLeftBottomChar, + $this->crossingTopMidBottomChar, + $this->crossingTopRightBottomChar, + ]; + } + + /** + * Sets header cell format. + * + * @return $this + */ + public function setCellHeaderFormat(string $cellHeaderFormat): static + { + $this->cellHeaderFormat = $cellHeaderFormat; + + return $this; + } + + /** + * Gets header cell format. + */ + public function getCellHeaderFormat(): string + { + return $this->cellHeaderFormat; + } + + /** + * Sets row cell format. + * + * @return $this + */ + public function setCellRowFormat(string $cellRowFormat): static + { + $this->cellRowFormat = $cellRowFormat; + + return $this; + } + + /** + * Gets row cell format. + */ + public function getCellRowFormat(): string + { + return $this->cellRowFormat; + } + + /** + * Sets row cell content format. + * + * @return $this + */ + public function setCellRowContentFormat(string $cellRowContentFormat): static + { + $this->cellRowContentFormat = $cellRowContentFormat; + + return $this; + } + + /** + * Gets row cell content format. + */ + public function getCellRowContentFormat(): string + { + return $this->cellRowContentFormat; + } + + /** + * Sets table border format. + * + * @return $this + */ + public function setBorderFormat(string $borderFormat): static + { + $this->borderFormat = $borderFormat; + + return $this; + } + + /** + * Gets table border format. + */ + public function getBorderFormat(): string + { + return $this->borderFormat; + } + + /** + * Sets cell padding type. + * + * @return $this + */ + public function setPadType(int $padType): static + { + if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) { + throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); + } + + $this->padType = $padType; + + return $this; + } + + /** + * Gets cell padding type. + */ + public function getPadType(): int + { + return $this->padType; + } + + public function getHeaderTitleFormat(): string + { + return $this->headerTitleFormat; + } + + /** + * @return $this + */ + public function setHeaderTitleFormat(string $format): static + { + $this->headerTitleFormat = $format; + + return $this; + } + + public function getFooterTitleFormat(): string + { + return $this->footerTitleFormat; + } + + /** + * @return $this + */ + public function setFooterTitleFormat(string $format): static + { + $this->footerTitleFormat = $format; + + return $this; + } +} diff --git a/cacme/vendor/symfony/console/Input/ArgvInput.php b/cacme/vendor/symfony/console/Input/ArgvInput.php new file mode 100644 index 0000000..4e90c81 --- /dev/null +++ b/cacme/vendor/symfony/console/Input/ArgvInput.php @@ -0,0 +1,376 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * ArgvInput represents an input coming from the CLI arguments. + * + * Usage: + * + * $input = new ArgvInput(); + * + * By default, the `$_SERVER['argv']` array is used for the input values. + * + * This can be overridden by explicitly passing the input values in the constructor: + * + * $input = new ArgvInput($_SERVER['argv']); + * + * If you pass it yourself, don't forget that the first element of the array + * is the name of the running application. + * + * When passing an argument to the constructor, be sure that it respects + * the same rules as the argv one. It's almost always better to use the + * `StringInput` when you want to provide your own input. + * + * @author Fabien Potencier + * + * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 + */ +class ArgvInput extends Input +{ + private array $tokens; + private array $parsed; + + public function __construct(array $argv = null, InputDefinition $definition = null) + { + $argv = $argv ?? $_SERVER['argv'] ?? []; + + // strip the application name + array_shift($argv); + + $this->tokens = $argv; + + parent::__construct($definition); + } + + protected function setTokens(array $tokens) + { + $this->tokens = $tokens; + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + $parseOptions = true; + $this->parsed = $this->tokens; + while (null !== $token = array_shift($this->parsed)) { + $parseOptions = $this->parseToken($token, $parseOptions); + } + } + + protected function parseToken(string $token, bool $parseOptions): bool + { + if ($parseOptions && '' == $token) { + $this->parseArgument($token); + } elseif ($parseOptions && '--' == $token) { + return false; + } elseif ($parseOptions && str_starts_with($token, '--')) { + $this->parseLongOption($token); + } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { + $this->parseShortOption($token); + } else { + $this->parseArgument($token); + } + + return $parseOptions; + } + + /** + * Parses a short option. + */ + private function parseShortOption(string $token) + { + $name = substr($token, 1); + + if (\strlen($name) > 1) { + if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { + // an option with a value (with no space) + $this->addShortOption($name[0], substr($name, 1)); + } else { + $this->parseShortOptionSet($name); + } + } else { + $this->addShortOption($name, null); + } + } + + /** + * Parses a short option set. + * + * @throws RuntimeException When option given doesn't exist + */ + private function parseShortOptionSet(string $name) + { + $len = \strlen($name); + for ($i = 0; $i < $len; ++$i) { + if (!$this->definition->hasShortcut($name[$i])) { + $encoding = mb_detect_encoding($name, null, true); + throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); + } + + $option = $this->definition->getOptionForShortcut($name[$i]); + if ($option->acceptValue()) { + $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); + + break; + } else { + $this->addLongOption($option->getName(), null); + } + } + } + + /** + * Parses a long option. + */ + private function parseLongOption(string $token) + { + $name = substr($token, 2); + + if (false !== $pos = strpos($name, '=')) { + if ('' === $value = substr($name, $pos + 1)) { + array_unshift($this->parsed, $value); + } + $this->addLongOption(substr($name, 0, $pos), $value); + } else { + $this->addLongOption($name, null); + } + } + + /** + * Parses an argument. + * + * @throws RuntimeException When too many arguments are given + */ + private function parseArgument(string $token) + { + $c = \count($this->arguments); + + // if input is expecting another argument, add it + if ($this->definition->hasArgument($c)) { + $arg = $this->definition->getArgument($c); + $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; + + // if last argument isArray(), append token to last argument + } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { + $arg = $this->definition->getArgument($c - 1); + $this->arguments[$arg->getName()][] = $token; + + // unexpected argument + } else { + $all = $this->definition->getArguments(); + $symfonyCommandName = null; + if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) { + $symfonyCommandName = $this->arguments['command'] ?? null; + unset($all[$key]); + } + + if (\count($all)) { + if ($symfonyCommandName) { + $message = sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all))); + } else { + $message = sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))); + } + } elseif ($symfonyCommandName) { + $message = sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token); + } else { + $message = sprintf('No arguments expected, got "%s".', $token); + } + + throw new RuntimeException($message); + } + } + + /** + * Adds a short option value. + * + * @throws RuntimeException When option given doesn't exist + */ + private function addShortOption(string $shortcut, mixed $value) + { + if (!$this->definition->hasShortcut($shortcut)) { + throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @throws RuntimeException When option given doesn't exist + */ + private function addLongOption(string $name, mixed $value) + { + if (!$this->definition->hasOption($name)) { + if (!$this->definition->hasNegation($name)) { + throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + } + + $optionName = $this->definition->negationToName($name); + if (null !== $value) { + throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + } + $this->options[$optionName] = false; + + return; + } + + $option = $this->definition->getOption($name); + + if (null !== $value && !$option->acceptValue()) { + throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + } + + if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { + // if option accepts an optional or mandatory argument + // let's see if there is one provided + $next = array_shift($this->parsed); + if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) { + $value = $next; + } else { + array_unshift($this->parsed, $next); + } + } + + if (null === $value) { + if ($option->isValueRequired()) { + throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isArray() && !$option->isValueOptional()) { + $value = true; + } + } + + if ($option->isArray()) { + $this->options[$name][] = $value; + } else { + $this->options[$name] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument(): ?string + { + $isOption = false; + foreach ($this->tokens as $i => $token) { + if ($token && '-' === $token[0]) { + if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) { + continue; + } + + // If it's a long option, consider that everything after "--" is the option name. + // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) + $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); + if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { + // noop + } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { + $isOption = true; + } + + continue; + } + + if ($isOption) { + $isOption = false; + continue; + } + + return $token; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption(string|array $values, bool $onlyParams = false): bool + { + $values = (array) $values; + + foreach ($this->tokens as $token) { + if ($onlyParams && '--' === $token) { + return false; + } + foreach ($values as $value) { + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = str_starts_with($value, '--') ? $value.'=' : $value; + if ($token === $value || '' !== $leading && str_starts_with($token, $leading)) { + return true; + } + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed + { + $values = (array) $values; + $tokens = $this->tokens; + + while (0 < \count($tokens)) { + $token = array_shift($tokens); + if ($onlyParams && '--' === $token) { + return $default; + } + + foreach ($values as $value) { + if ($token === $value) { + return array_shift($tokens); + } + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = str_starts_with($value, '--') ? $value.'=' : $value; + if ('' !== $leading && str_starts_with($token, $leading)) { + return substr($token, \strlen($leading)); + } + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + */ + public function __toString(): string + { + $tokens = array_map(function ($token) { + if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { + return $match[1].$this->escapeToken($match[2]); + } + + if ($token && '-' !== $token[0]) { + return $this->escapeToken($token); + } + + return $token; + }, $this->tokens); + + return implode(' ', $tokens); + } +} diff --git a/cacme/vendor/symfony/console/Input/ArrayInput.php b/cacme/vendor/symfony/console/Input/ArrayInput.php new file mode 100644 index 0000000..fdb47df --- /dev/null +++ b/cacme/vendor/symfony/console/Input/ArrayInput.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 Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\InvalidOptionException; + +/** + * ArrayInput represents an input provided as an array. + * + * Usage: + * + * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); + * + * @author Fabien Potencier + */ +class ArrayInput extends Input +{ + private array $parameters; + + public function __construct(array $parameters, InputDefinition $definition = null) + { + $this->parameters = $parameters; + + parent::__construct($definition); + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument(): ?string + { + foreach ($this->parameters as $param => $value) { + if ($param && \is_string($param) && '-' === $param[0]) { + continue; + } + + return $value; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption(string|array $values, bool $onlyParams = false): bool + { + $values = (array) $values; + + foreach ($this->parameters as $k => $v) { + if (!\is_int($k)) { + $v = $k; + } + + if ($onlyParams && '--' === $v) { + return false; + } + + if (\in_array($v, $values)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed + { + $values = (array) $values; + + foreach ($this->parameters as $k => $v) { + if ($onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))) { + return $default; + } + + if (\is_int($k)) { + if (\in_array($v, $values)) { + return true; + } + } elseif (\in_array($k, $values)) { + return $v; + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + */ + public function __toString(): string + { + $params = []; + foreach ($this->parameters as $param => $val) { + if ($param && \is_string($param) && '-' === $param[0]) { + $glue = ('-' === $param[1]) ? '=' : ' '; + if (\is_array($val)) { + foreach ($val as $v) { + $params[] = $param.('' != $v ? $glue.$this->escapeToken($v) : ''); + } + } else { + $params[] = $param.('' != $val ? $glue.$this->escapeToken($val) : ''); + } + } else { + $params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); + } + } + + return implode(' ', $params); + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + foreach ($this->parameters as $key => $value) { + if ('--' === $key) { + return; + } + if (str_starts_with($key, '--')) { + $this->addLongOption(substr($key, 2), $value); + } elseif (str_starts_with($key, '-')) { + $this->addShortOption(substr($key, 1), $value); + } else { + $this->addArgument($key, $value); + } + } + } + + /** + * Adds a short option value. + * + * @throws InvalidOptionException When option given doesn't exist + */ + private function addShortOption(string $shortcut, mixed $value) + { + if (!$this->definition->hasShortcut($shortcut)) { + throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @throws InvalidOptionException When option given doesn't exist + * @throws InvalidOptionException When a required value is missing + */ + private function addLongOption(string $name, mixed $value) + { + if (!$this->definition->hasOption($name)) { + if (!$this->definition->hasNegation($name)) { + throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); + } + + $optionName = $this->definition->negationToName($name); + $this->options[$optionName] = false; + + return; + } + + $option = $this->definition->getOption($name); + + if (null === $value) { + if ($option->isValueRequired()) { + throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isValueOptional()) { + $value = true; + } + } + + $this->options[$name] = $value; + } + + /** + * Adds an argument value. + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + private function addArgument(string|int $name, mixed $value) + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } +} diff --git a/cacme/vendor/symfony/console/Input/Input.php b/cacme/vendor/symfony/console/Input/Input.php new file mode 100644 index 0000000..1db503c --- /dev/null +++ b/cacme/vendor/symfony/console/Input/Input.php @@ -0,0 +1,211 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * Input is the base class for all concrete Input classes. + * + * Three concrete classes are provided by default: + * + * * `ArgvInput`: The input comes from the CLI arguments (argv) + * * `StringInput`: The input is provided as a string + * * `ArrayInput`: The input is provided as an array + * + * @author Fabien Potencier + */ +abstract class Input implements InputInterface, StreamableInputInterface +{ + protected $definition; + protected $stream; + protected $options = []; + protected $arguments = []; + protected $interactive = true; + + public function __construct(InputDefinition $definition = null) + { + if (null === $definition) { + $this->definition = new InputDefinition(); + } else { + $this->bind($definition); + $this->validate(); + } + } + + /** + * {@inheritdoc} + */ + public function bind(InputDefinition $definition) + { + $this->arguments = []; + $this->options = []; + $this->definition = $definition; + + $this->parse(); + } + + /** + * Processes command line arguments. + */ + abstract protected function parse(); + + /** + * {@inheritdoc} + */ + public function validate() + { + $definition = $this->definition; + $givenArguments = $this->arguments; + + $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { + return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); + }); + + if (\count($missingArguments) > 0) { + throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); + } + } + + /** + * {@inheritdoc} + */ + public function isInteractive(): bool + { + return $this->interactive; + } + + /** + * {@inheritdoc} + */ + public function setInteractive(bool $interactive) + { + $this->interactive = $interactive; + } + + /** + * {@inheritdoc} + */ + public function getArguments(): array + { + return array_merge($this->definition->getArgumentDefaults(), $this->arguments); + } + + /** + * {@inheritdoc} + */ + public function getArgument(string $name): mixed + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function setArgument(string $name, mixed $value) + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function hasArgument(string $name): bool + { + return $this->definition->hasArgument($name); + } + + /** + * {@inheritdoc} + */ + public function getOptions(): array + { + return array_merge($this->definition->getOptionDefaults(), $this->options); + } + + /** + * {@inheritdoc} + */ + public function getOption(string $name): mixed + { + if ($this->definition->hasNegation($name)) { + if (null === $value = $this->getOption($this->definition->negationToName($name))) { + return $value; + } + + return !$value; + } + + if (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function setOption(string $name, mixed $value) + { + if ($this->definition->hasNegation($name)) { + $this->options[$this->definition->negationToName($name)] = !$value; + + return; + } elseif (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + $this->options[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function hasOption(string $name): bool + { + return $this->definition->hasOption($name) || $this->definition->hasNegation($name); + } + + /** + * Escapes a token through escapeshellarg if it contains unsafe chars. + */ + public function escapeToken(string $token): string + { + return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); + } + + /** + * {@inheritdoc} + */ + public function setStream($stream) + { + $this->stream = $stream; + } + + /** + * {@inheritdoc} + */ + public function getStream() + { + return $this->stream; + } +} diff --git a/cacme/vendor/symfony/console/Input/InputArgument.php b/cacme/vendor/symfony/console/Input/InputArgument.php new file mode 100644 index 0000000..1e666ee --- /dev/null +++ b/cacme/vendor/symfony/console/Input/InputArgument.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 Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line argument. + * + * @author Fabien Potencier + */ +class InputArgument +{ + public const REQUIRED = 1; + public const OPTIONAL = 2; + public const IS_ARRAY = 4; + + private string $name; + private int $mode; + private string|int|bool|array|null|float $default; + private string $description; + + /** + * @param string $name The argument name + * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL + * @param string $description A description text + * @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only) + * + * @throws InvalidArgumentException When argument mode is not valid + */ + public function __construct(string $name, int $mode = null, string $description = '', string|bool|int|float|array $default = null) + { + if (null === $mode) { + $mode = self::OPTIONAL; + } elseif ($mode > 7 || $mode < 1) { + throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->mode = $mode; + $this->description = $description; + + $this->setDefault($default); + } + + /** + * Returns the argument name. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Returns true if the argument is required. + * + * @return bool true if parameter mode is self::REQUIRED, false otherwise + */ + public function isRequired(): bool + { + return self::REQUIRED === (self::REQUIRED & $this->mode); + } + + /** + * Returns true if the argument can take multiple values. + * + * @return bool true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray(): bool + { + return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); + } + + /** + * Sets the default value. + * + * @throws LogicException When incorrect default value is given + */ + public function setDefault(string|bool|int|float|array $default = null) + { + if ($this->isRequired() && null !== $default) { + throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!\is_array($default)) { + throw new LogicException('A default value for an array argument must be an array.'); + } + } + + $this->default = $default; + } + + /** + * Returns the default value. + */ + public function getDefault(): string|bool|int|float|array|null + { + return $this->default; + } + + /** + * Returns the description text. + */ + public function getDescription(): string + { + return $this->description; + } +} diff --git a/cacme/vendor/symfony/console/Input/InputAwareInterface.php b/cacme/vendor/symfony/console/Input/InputAwareInterface.php new file mode 100644 index 0000000..5a288de --- /dev/null +++ b/cacme/vendor/symfony/console/Input/InputAwareInterface.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\Console\Input; + +/** + * InputAwareInterface should be implemented by classes that depends on the + * Console Input. + * + * @author Wouter J + */ +interface InputAwareInterface +{ + /** + * Sets the Console Input. + */ + public function setInput(InputInterface $input); +} diff --git a/cacme/vendor/symfony/console/Input/InputDefinition.php b/cacme/vendor/symfony/console/Input/InputDefinition.php new file mode 100644 index 0000000..cb270d8 --- /dev/null +++ b/cacme/vendor/symfony/console/Input/InputDefinition.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 Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * A InputDefinition represents a set of valid command line arguments and options. + * + * Usage: + * + * $definition = new InputDefinition([ + * new InputArgument('name', InputArgument::REQUIRED), + * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), + * ]); + * + * @author Fabien Potencier + */ +class InputDefinition +{ + private array $arguments = []; + private int $requiredCount = 0; + private $lastArrayArgument = null; + private $lastOptionalArgument = null; + private array $options = []; + private array $negations = []; + private array $shortcuts = []; + + /** + * @param array $definition An array of InputArgument and InputOption instance + */ + public function __construct(array $definition = []) + { + $this->setDefinition($definition); + } + + /** + * Sets the definition of the input. + */ + public function setDefinition(array $definition) + { + $arguments = []; + $options = []; + foreach ($definition as $item) { + if ($item instanceof InputOption) { + $options[] = $item; + } else { + $arguments[] = $item; + } + } + + $this->setArguments($arguments); + $this->setOptions($options); + } + + /** + * Sets the InputArgument objects. + * + * @param InputArgument[] $arguments An array of InputArgument objects + */ + public function setArguments(array $arguments = []) + { + $this->arguments = []; + $this->requiredCount = 0; + $this->lastOptionalArgument = null; + $this->lastArrayArgument = null; + $this->addArguments($arguments); + } + + /** + * Adds an array of InputArgument objects. + * + * @param InputArgument[] $arguments An array of InputArgument objects + */ + public function addArguments(?array $arguments = []) + { + if (null !== $arguments) { + foreach ($arguments as $argument) { + $this->addArgument($argument); + } + } + } + + /** + * @throws LogicException When incorrect argument is given + */ + public function addArgument(InputArgument $argument) + { + if (isset($this->arguments[$argument->getName()])) { + throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); + } + + if (null !== $this->lastArrayArgument) { + throw new LogicException(sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName())); + } + + if ($argument->isRequired() && null !== $this->lastOptionalArgument) { + throw new LogicException(sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName())); + } + + if ($argument->isArray()) { + $this->lastArrayArgument = $argument; + } + + if ($argument->isRequired()) { + ++$this->requiredCount; + } else { + $this->lastOptionalArgument = $argument; + } + + $this->arguments[$argument->getName()] = $argument; + } + + /** + * Returns an InputArgument by name or by position. + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument(string|int $name): InputArgument + { + if (!$this->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; + + return $arguments[$name]; + } + + /** + * Returns true if an InputArgument object exists by name or position. + */ + public function hasArgument(string|int $name): bool + { + $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; + + return isset($arguments[$name]); + } + + /** + * Gets the array of InputArgument objects. + * + * @return InputArgument[] + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * Returns the number of InputArguments. + */ + public function getArgumentCount(): int + { + return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments); + } + + /** + * Returns the number of required InputArguments. + */ + public function getArgumentRequiredCount(): int + { + return $this->requiredCount; + } + + /** + * @return array + */ + public function getArgumentDefaults(): array + { + $values = []; + foreach ($this->arguments as $argument) { + $values[$argument->getName()] = $argument->getDefault(); + } + + return $values; + } + + /** + * Sets the InputOption objects. + * + * @param InputOption[] $options An array of InputOption objects + */ + public function setOptions(array $options = []) + { + $this->options = []; + $this->shortcuts = []; + $this->negations = []; + $this->addOptions($options); + } + + /** + * Adds an array of InputOption objects. + * + * @param InputOption[] $options An array of InputOption objects + */ + public function addOptions(array $options = []) + { + foreach ($options as $option) { + $this->addOption($option); + } + } + + /** + * @throws LogicException When option given already exist + */ + public function addOption(InputOption $option) + { + if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + } + if (isset($this->negations[$option->getName()])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + } + + if ($option->getShortcut()) { + foreach (explode('|', $option->getShortcut()) as $shortcut) { + if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { + throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); + } + } + } + + $this->options[$option->getName()] = $option; + if ($option->getShortcut()) { + foreach (explode('|', $option->getShortcut()) as $shortcut) { + $this->shortcuts[$shortcut] = $option->getName(); + } + } + + if ($option->isNegatable()) { + $negatedName = 'no-'.$option->getName(); + if (isset($this->options[$negatedName])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $negatedName)); + } + $this->negations[$negatedName] = $option->getName(); + } + } + + /** + * Returns an InputOption by name. + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption(string $name): InputOption + { + if (!$this->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); + } + + return $this->options[$name]; + } + + /** + * Returns true if an InputOption object exists by name. + * + * This method can't be used to check if the user included the option when + * executing the command (use getOption() instead). + */ + public function hasOption(string $name): bool + { + return isset($this->options[$name]); + } + + /** + * Gets the array of InputOption objects. + * + * @return InputOption[] + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * Returns true if an InputOption object exists by shortcut. + */ + public function hasShortcut(string $name): bool + { + return isset($this->shortcuts[$name]); + } + + /** + * Returns true if an InputOption object exists by negated name. + */ + public function hasNegation(string $name): bool + { + return isset($this->negations[$name]); + } + + /** + * Gets an InputOption by shortcut. + */ + public function getOptionForShortcut(string $shortcut): InputOption + { + return $this->getOption($this->shortcutToName($shortcut)); + } + + /** + * @return array + */ + public function getOptionDefaults(): array + { + $values = []; + foreach ($this->options as $option) { + $values[$option->getName()] = $option->getDefault(); + } + + return $values; + } + + /** + * Returns the InputOption name given a shortcut. + * + * @throws InvalidArgumentException When option given does not exist + * + * @internal + */ + public function shortcutToName(string $shortcut): string + { + if (!isset($this->shortcuts[$shortcut])) { + throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + return $this->shortcuts[$shortcut]; + } + + /** + * Returns the InputOption name given a negation. + * + * @throws InvalidArgumentException When option given does not exist + * + * @internal + */ + public function negationToName(string $negation): string + { + if (!isset($this->negations[$negation])) { + throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $negation)); + } + + return $this->negations[$negation]; + } + + /** + * Gets the synopsis. + */ + public function getSynopsis(bool $short = false): string + { + $elements = []; + + if ($short && $this->getOptions()) { + $elements[] = '[options]'; + } elseif (!$short) { + foreach ($this->getOptions() as $option) { + $value = ''; + if ($option->acceptValue()) { + $value = sprintf( + ' %s%s%s', + $option->isValueOptional() ? '[' : '', + strtoupper($option->getName()), + $option->isValueOptional() ? ']' : '' + ); + } + + $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; + $negation = $option->isNegatable() ? sprintf('|--no-%s', $option->getName()) : ''; + $elements[] = sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation); + } + } + + if (\count($elements) && $this->getArguments()) { + $elements[] = '[--]'; + } + + $tail = ''; + foreach ($this->getArguments() as $argument) { + $element = '<'.$argument->getName().'>'; + if ($argument->isArray()) { + $element .= '...'; + } + + if (!$argument->isRequired()) { + $element = '['.$element; + $tail .= ']'; + } + + $elements[] = $element; + } + + return implode(' ', $elements).$tail; + } +} diff --git a/cacme/vendor/symfony/console/Input/InputInterface.php b/cacme/vendor/symfony/console/Input/InputInterface.php new file mode 100644 index 0000000..024da18 --- /dev/null +++ b/cacme/vendor/symfony/console/Input/InputInterface.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 Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * InputInterface is the interface implemented by all input classes. + * + * @author Fabien Potencier + */ +interface InputInterface +{ + /** + * Returns the first argument from the raw parameters (not parsed). + */ + public function getFirstArgument(): ?string; + + /** + * Returns true if the raw parameters (not parsed) contain a value. + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The values to look for in the raw parameters (can be an array) + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + */ + public function hasParameterOption(string|array $values, bool $onlyParams = false): bool; + + /** + * Returns the value of a raw option (not parsed). + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param string|bool|int|float|array|null $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * + * @return mixed + */ + public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false); + + /** + * Binds the current Input instance with the given arguments and options. + * + * @throws RuntimeException + */ + public function bind(InputDefinition $definition); + + /** + * Validates the input. + * + * @throws RuntimeException When not enough arguments are given + */ + public function validate(); + + /** + * Returns all the given arguments merged with the default values. + * + * @return array + */ + public function getArguments(): array; + + /** + * Returns the argument value for a given argument name. + * + * @return mixed + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument(string $name); + + /** + * Sets an argument value by name. + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function setArgument(string $name, mixed $value); + + /** + * Returns true if an InputArgument object exists by name or position. + */ + public function hasArgument(string $name): bool; + + /** + * Returns all the given options merged with the default values. + * + * @return array + */ + public function getOptions(): array; + + /** + * Returns the option value for a given option name. + * + * @return mixed + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption(string $name); + + /** + * Sets an option value by name. + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function setOption(string $name, mixed $value); + + /** + * Returns true if an InputOption object exists by name. + */ + public function hasOption(string $name): bool; + + /** + * Is this input means interactive? + */ + public function isInteractive(): bool; + + /** + * Sets the input interactivity. + */ + public function setInteractive(bool $interactive); +} diff --git a/cacme/vendor/symfony/console/Input/InputOption.php b/cacme/vendor/symfony/console/Input/InputOption.php new file mode 100644 index 0000000..f9d74a8 --- /dev/null +++ b/cacme/vendor/symfony/console/Input/InputOption.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line option. + * + * @author Fabien Potencier + */ +class InputOption +{ + /** + * Do not accept input for the option (e.g. --yell). This is the default behavior of options. + */ + public const VALUE_NONE = 1; + + /** + * A value must be passed when the option is used (e.g. --iterations=5 or -i5). + */ + public const VALUE_REQUIRED = 2; + + /** + * The option may or may not have a value (e.g. --yell or --yell=loud). + */ + public const VALUE_OPTIONAL = 4; + + /** + * The option accepts multiple values (e.g. --dir=/foo --dir=/bar). + */ + public const VALUE_IS_ARRAY = 8; + + /** + * The option may have either positive or negative value (e.g. --ansi or --no-ansi). + */ + public const VALUE_NEGATABLE = 16; + + private string $name; + private string|array|null $shortcut; + private int $mode; + private string|int|bool|array|null|float $default; + private string $description; + + /** + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the VALUE_* constants + * @param string|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE) + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + */ + public function __construct(string $name, string|array $shortcut = null, int $mode = null, string $description = '', string|bool|int|float|array $default = null) + { + if (str_starts_with($name, '--')) { + $name = substr($name, 2); + } + + if (empty($name)) { + throw new InvalidArgumentException('An option name cannot be empty.'); + } + + if (empty($shortcut)) { + $shortcut = null; + } + + if (null !== $shortcut) { + if (\is_array($shortcut)) { + $shortcut = implode('|', $shortcut); + } + $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); + $shortcuts = array_filter($shortcuts); + $shortcut = implode('|', $shortcuts); + + if (empty($shortcut)) { + throw new InvalidArgumentException('An option shortcut cannot be empty.'); + } + } + + if (null === $mode) { + $mode = self::VALUE_NONE; + } elseif ($mode >= (self::VALUE_NEGATABLE << 1) || $mode < 1) { + throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->shortcut = $shortcut; + $this->mode = $mode; + $this->description = $description; + + if ($this->isArray() && !$this->acceptValue()) { + throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); + } + if ($this->isNegatable() && $this->acceptValue()) { + throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.'); + } + + $this->setDefault($default); + } + + /** + * Returns the option shortcut. + */ + public function getShortcut(): ?string + { + return $this->shortcut; + } + + /** + * Returns the option name. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Returns true if the option accepts a value. + * + * @return bool true if value mode is not self::VALUE_NONE, false otherwise + */ + public function acceptValue(): bool + { + return $this->isValueRequired() || $this->isValueOptional(); + } + + /** + * Returns true if the option requires a value. + * + * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise + */ + public function isValueRequired(): bool + { + return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); + } + + /** + * Returns true if the option takes an optional value. + * + * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise + */ + public function isValueOptional(): bool + { + return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); + } + + /** + * Returns true if the option can take multiple values. + * + * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise + */ + public function isArray(): bool + { + return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); + } + + public function isNegatable(): bool + { + return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode); + } + + public function setDefault(string|bool|int|float|array $default = null) + { + if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { + throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!\is_array($default)) { + throw new LogicException('A default value for an array option must be an array.'); + } + } + + $this->default = $this->acceptValue() || $this->isNegatable() ? $default : false; + } + + /** + * Returns the default value. + */ + public function getDefault(): string|bool|int|float|array|null + { + return $this->default; + } + + /** + * Returns the description text. + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * Checks whether the given option equals this one. + */ + public function equals(self $option): bool + { + return $option->getName() === $this->getName() + && $option->getShortcut() === $this->getShortcut() + && $option->getDefault() === $this->getDefault() + && $option->isNegatable() === $this->isNegatable() + && $option->isArray() === $this->isArray() + && $option->isValueRequired() === $this->isValueRequired() + && $option->isValueOptional() === $this->isValueOptional() + ; + } +} diff --git a/cacme/vendor/symfony/console/Input/StreamableInputInterface.php b/cacme/vendor/symfony/console/Input/StreamableInputInterface.php new file mode 100644 index 0000000..d7e462f --- /dev/null +++ b/cacme/vendor/symfony/console/Input/StreamableInputInterface.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\Console\Input; + +/** + * StreamableInputInterface is the interface implemented by all input classes + * that have an input stream. + * + * @author Robin Chalas + */ +interface StreamableInputInterface extends InputInterface +{ + /** + * Sets the input stream to read from when interacting with the user. + * + * This is mainly useful for testing purpose. + * + * @param resource $stream The input stream + */ + public function setStream($stream); + + /** + * Returns the input stream. + * + * @return resource|null + */ + public function getStream(); +} diff --git a/cacme/vendor/symfony/console/Input/StringInput.php b/cacme/vendor/symfony/console/Input/StringInput.php new file mode 100644 index 0000000..56bb66c --- /dev/null +++ b/cacme/vendor/symfony/console/Input/StringInput.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 Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * StringInput represents an input provided as a string. + * + * Usage: + * + * $input = new StringInput('foo --bar="foobar"'); + * + * @author Fabien Potencier + */ +class StringInput extends ArgvInput +{ + public const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); + } + + /** + * Tokenizes a string. + * + * @throws InvalidArgumentException When unable to parse input (should never happen) + */ + private function tokenize(string $input): array + { + $tokens = []; + $length = \strlen($input); + $cursor = 0; + $token = null; + while ($cursor < $length) { + if ('\\' === $input[$cursor]) { + $token .= $input[++$cursor] ?? ''; + ++$cursor; + continue; + } + + if (preg_match('/\s+/A', $input, $match, 0, $cursor)) { + if (null !== $token) { + $tokens[] = $token; + $token = null; + } + } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) { + $token .= $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1))); + } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) { + $token .= stripcslashes(substr($match[0], 1, -1)); + } elseif (preg_match('/'.self::REGEX_UNQUOTED_STRING.'/A', $input, $match, 0, $cursor)) { + $token .= $match[1]; + } else { + // should never happen + throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10))); + } + + $cursor += \strlen($match[0]); + } + + if (null !== $token) { + $tokens[] = $token; + } + + return $tokens; + } +} diff --git a/cacme/vendor/symfony/console/LICENSE b/cacme/vendor/symfony/console/LICENSE new file mode 100644 index 0000000..0083704 --- /dev/null +++ b/cacme/vendor/symfony/console/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2023 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/cacme/vendor/symfony/console/Logger/ConsoleLogger.php b/cacme/vendor/symfony/console/Logger/ConsoleLogger.php new file mode 100644 index 0000000..c9714c3 --- /dev/null +++ b/cacme/vendor/symfony/console/Logger/ConsoleLogger.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 Symfony\Component\Console\Logger; + +use Psr\Log\AbstractLogger; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * PSR-3 compliant console logger. + * + * @author Kévin Dunglas + * + * @see https://www.php-fig.org/psr/psr-3/ + */ +class ConsoleLogger extends AbstractLogger +{ + public const INFO = 'info'; + public const ERROR = 'error'; + + private $output; + private array $verbosityLevelMap = [ + LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, + LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, + LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, + LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, + LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, + LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, + LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, + LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, + ]; + private array $formatLevelMap = [ + LogLevel::EMERGENCY => self::ERROR, + LogLevel::ALERT => self::ERROR, + LogLevel::CRITICAL => self::ERROR, + LogLevel::ERROR => self::ERROR, + LogLevel::WARNING => self::INFO, + LogLevel::NOTICE => self::INFO, + LogLevel::INFO => self::INFO, + LogLevel::DEBUG => self::INFO, + ]; + private bool $errored = false; + + public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) + { + $this->output = $output; + $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; + $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; + } + + /** + * {@inheritdoc} + */ + public function log($level, $message, array $context = []): void + { + if (!isset($this->verbosityLevelMap[$level])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + } + + $output = $this->output; + + // Write to the error output if necessary and available + if (self::ERROR === $this->formatLevelMap[$level]) { + if ($this->output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $this->errored = true; + } + + // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. + // We only do it for efficiency here as the message formatting is relatively expensive. + if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { + $output->writeln(sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); + } + } + + /** + * Returns true when any messages have been logged at error levels. + */ + public function hasErrored(): bool + { + return $this->errored; + } + + /** + * Interpolates context values into the message placeholders. + * + * @author PHP Framework Interoperability Group + */ + private function interpolate(string $message, array $context): string + { + if (!str_contains($message, '{')) { + return $message; + } + + $replacements = []; + foreach ($context as $key => $val) { + if (null === $val || \is_scalar($val) || $val instanceof \Stringable) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + return strtr($message, $replacements); + } +} diff --git a/cacme/vendor/symfony/console/Output/BufferedOutput.php b/cacme/vendor/symfony/console/Output/BufferedOutput.php new file mode 100644 index 0000000..784e309 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/BufferedOutput.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\Console\Output; + +/** + * @author Jean-François Simon + */ +class BufferedOutput extends Output +{ + private string $buffer = ''; + + /** + * Empties buffer and returns its content. + */ + public function fetch(): string + { + $content = $this->buffer; + $this->buffer = ''; + + return $content; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + $this->buffer .= $message; + + if ($newline) { + $this->buffer .= \PHP_EOL; + } + } +} diff --git a/cacme/vendor/symfony/console/Output/ConsoleOutput.php b/cacme/vendor/symfony/console/Output/ConsoleOutput.php new file mode 100644 index 0000000..c6ba068 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/ConsoleOutput.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR. + * + * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR. + * + * $output = new ConsoleOutput(); + * + * This is equivalent to: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * $stdErr = new StreamOutput(fopen('php://stderr', 'w')); + * + * @author Fabien Potencier + */ +class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface +{ + private $stderr; + private array $consoleSectionOutputs = []; + + /** + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + */ + public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) + { + parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + + if (null === $formatter) { + // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter. + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated); + + return; + } + + $actualDecorated = $this->isDecorated(); + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); + + if (null === $decorated) { + $this->setDecorated($actualDecorated && $this->stderr->isDecorated()); + } + } + + /** + * Creates a new output section. + */ + public function section(): ConsoleSectionOutput + { + return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + parent::setDecorated($decorated); + $this->stderr->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + parent::setFormatter($formatter); + $this->stderr->setFormatter($formatter); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + parent::setVerbosity($level); + $this->stderr->setVerbosity($level); + } + + /** + * {@inheritdoc} + */ + public function getErrorOutput(): OutputInterface + { + return $this->stderr; + } + + /** + * {@inheritdoc} + */ + public function setErrorOutput(OutputInterface $error) + { + $this->stderr = $error; + } + + /** + * Returns true if current environment supports writing console output to + * STDOUT. + */ + protected function hasStdoutSupport(): bool + { + return false === $this->isRunningOS400(); + } + + /** + * Returns true if current environment supports writing console output to + * STDERR. + */ + protected function hasStderrSupport(): bool + { + return false === $this->isRunningOS400(); + } + + /** + * Checks if current executing environment is IBM iSeries (OS400), which + * doesn't properly convert character-encodings between ASCII to EBCDIC. + */ + private function isRunningOS400(): bool + { + $checks = [ + \function_exists('php_uname') ? php_uname('s') : '', + getenv('OSTYPE'), + \PHP_OS, + ]; + + return false !== stripos(implode(';', $checks), 'OS400'); + } + + /** + * @return resource + */ + private function openOutputStream() + { + if (!$this->hasStdoutSupport()) { + return fopen('php://output', 'w'); + } + + // Use STDOUT when possible to prevent from opening too many file descriptors + return \defined('STDOUT') ? \STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w')); + } + + /** + * @return resource + */ + private function openErrorStream() + { + if (!$this->hasStderrSupport()) { + return fopen('php://output', 'w'); + } + + // Use STDERR when possible to prevent from opening too many file descriptors + return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w')); + } +} diff --git a/cacme/vendor/symfony/console/Output/ConsoleOutputInterface.php b/cacme/vendor/symfony/console/Output/ConsoleOutputInterface.php new file mode 100644 index 0000000..6b4babc --- /dev/null +++ b/cacme/vendor/symfony/console/Output/ConsoleOutputInterface.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\Console\Output; + +/** + * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. + * This adds information about stderr and section output stream. + * + * @author Dariusz Górecki + */ +interface ConsoleOutputInterface extends OutputInterface +{ + /** + * Gets the OutputInterface for errors. + */ + public function getErrorOutput(): OutputInterface; + + public function setErrorOutput(OutputInterface $error); + + public function section(): ConsoleSectionOutput; +} diff --git a/cacme/vendor/symfony/console/Output/ConsoleSectionOutput.php b/cacme/vendor/symfony/console/Output/ConsoleSectionOutput.php new file mode 100644 index 0000000..92dca79 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/ConsoleSectionOutput.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\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Terminal; + +/** + * @author Pierre du Plessis + * @author Gabriel Ostrolucký + */ +class ConsoleSectionOutput extends StreamOutput +{ + private array $content = []; + private int $lines = 0; + private array $sections; + private $terminal; + + /** + * @param resource $stream + * @param ConsoleSectionOutput[] $sections + */ + public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter) + { + parent::__construct($stream, $verbosity, $decorated, $formatter); + array_unshift($sections, $this); + $this->sections = &$sections; + $this->terminal = new Terminal(); + } + + /** + * Clears previous output for this section. + * + * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared + */ + public function clear(int $lines = null) + { + if (empty($this->content) || !$this->isDecorated()) { + return; + } + + if ($lines) { + array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content + } else { + $lines = $this->lines; + $this->content = []; + } + + $this->lines -= $lines; + + parent::doWrite($this->popStreamContentUntilCurrentSection($lines), false); + } + + /** + * Overwrites the previous output with a new message. + */ + public function overwrite(string|iterable $message) + { + $this->clear(); + $this->writeln($message); + } + + public function getContent(): string + { + return implode('', $this->content); + } + + /** + * @internal + */ + public function addContent(string $input) + { + foreach (explode(\PHP_EOL, $input) as $lineContent) { + $this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; + $this->content[] = $lineContent; + $this->content[] = \PHP_EOL; + } + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + if (!$this->isDecorated()) { + parent::doWrite($message, $newline); + + return; + } + + $erasedContent = $this->popStreamContentUntilCurrentSection(); + + $this->addContent($message); + + parent::doWrite($message, true); + parent::doWrite($erasedContent, false); + } + + /** + * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits + * current section. Then it erases content it crawled through. Optionally, it erases part of current section too. + */ + private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string + { + $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection; + $erasedContent = []; + + foreach ($this->sections as $section) { + if ($section === $this) { + break; + } + + $numberOfLinesToClear += $section->lines; + $erasedContent[] = $section->getContent(); + } + + if ($numberOfLinesToClear > 0) { + // move cursor up n lines + parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false); + // erase to end of screen + parent::doWrite("\x1b[0J", false); + } + + return implode('', array_reverse($erasedContent)); + } + + private function getDisplayLength(string $text): int + { + return Helper::width(Helper::removeDecoration($this->getFormatter(), str_replace("\t", ' ', $text))); + } +} diff --git a/cacme/vendor/symfony/console/Output/NullOutput.php b/cacme/vendor/symfony/console/Output/NullOutput.php new file mode 100644 index 0000000..87214ec --- /dev/null +++ b/cacme/vendor/symfony/console/Output/NullOutput.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 Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\NullOutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * NullOutput suppresses all output. + * + * $output = new NullOutput(); + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class NullOutput implements OutputInterface +{ + private $formatter; + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function getFormatter(): OutputFormatterInterface + { + // to comply with the interface we must return a OutputFormatterInterface + return $this->formatter ??= new NullOutputFormatter(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function isDecorated(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function getVerbosity(): int + { + return self::VERBOSITY_QUIET; + } + + /** + * {@inheritdoc} + */ + public function isQuiet(): bool + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isVerbose(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isDebug(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) + { + // do nothing + } +} diff --git a/cacme/vendor/symfony/console/Output/Output.php b/cacme/vendor/symfony/console/Output/Output.php new file mode 100644 index 0000000..58c1837 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/Output.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * Base class for output classes. + * + * There are five levels of verbosity: + * + * * normal: no option passed (normal output) + * * verbose: -v (more output) + * * very verbose: -vv (highly extended output) + * * debug: -vvv (all debug output) + * * quiet: -q (no output) + * + * @author Fabien Potencier + */ +abstract class Output implements OutputInterface +{ + private int $verbosity; + private $formatter; + + /** + * @param int|null $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool $decorated Whether to decorate messages + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + */ + public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) + { + $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL; + $this->formatter = $formatter ?? new OutputFormatter(); + $this->formatter->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + $this->formatter = $formatter; + } + + /** + * {@inheritdoc} + */ + public function getFormatter(): OutputFormatterInterface + { + return $this->formatter; + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + $this->formatter->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function isDecorated(): bool + { + return $this->formatter->isDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + $this->verbosity = $level; + } + + /** + * {@inheritdoc} + */ + public function getVerbosity(): int + { + return $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isQuiet(): bool + { + return self::VERBOSITY_QUIET === $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isVerbose(): bool + { + return self::VERBOSITY_VERBOSE <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose(): bool + { + return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isDebug(): bool + { + return self::VERBOSITY_DEBUG <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL) + { + $this->write($messages, true, $options); + } + + /** + * {@inheritdoc} + */ + public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) + { + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN; + $type = $types & $options ?: self::OUTPUT_NORMAL; + + $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG; + $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL; + + if ($verbosity > $this->getVerbosity()) { + return; + } + + foreach ($messages as $message) { + switch ($type) { + case OutputInterface::OUTPUT_NORMAL: + $message = $this->formatter->format($message); + break; + case OutputInterface::OUTPUT_RAW: + break; + case OutputInterface::OUTPUT_PLAIN: + $message = strip_tags($this->formatter->format($message)); + break; + } + + $this->doWrite($message ?? '', $newline); + } + } + + /** + * Writes a message to the output. + */ + abstract protected function doWrite(string $message, bool $newline); +} diff --git a/cacme/vendor/symfony/console/Output/OutputInterface.php b/cacme/vendor/symfony/console/Output/OutputInterface.php new file mode 100644 index 0000000..beb9218 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/OutputInterface.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\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * OutputInterface is the interface implemented by all Output classes. + * + * @author Fabien Potencier + */ +interface OutputInterface +{ + public const VERBOSITY_QUIET = 16; + public const VERBOSITY_NORMAL = 32; + public const VERBOSITY_VERBOSE = 64; + public const VERBOSITY_VERY_VERBOSE = 128; + public const VERBOSITY_DEBUG = 256; + + public const OUTPUT_NORMAL = 1; + public const OUTPUT_RAW = 2; + public const OUTPUT_PLAIN = 4; + + /** + * Writes a message to the output. + * + * @param $newline Whether to add a newline + * @param $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + */ + public function write(string|iterable $messages, bool $newline = false, int $options = 0); + + /** + * Writes a message to the output and adds a newline at the end. + * + * @param $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + */ + public function writeln(string|iterable $messages, int $options = 0); + + /** + * Sets the verbosity of the output. + */ + public function setVerbosity(int $level); + + /** + * Gets the current verbosity of the output. + */ + public function getVerbosity(): int; + + /** + * Returns whether verbosity is quiet (-q). + */ + public function isQuiet(): bool; + + /** + * Returns whether verbosity is verbose (-v). + */ + public function isVerbose(): bool; + + /** + * Returns whether verbosity is very verbose (-vv). + */ + public function isVeryVerbose(): bool; + + /** + * Returns whether verbosity is debug (-vvv). + */ + public function isDebug(): bool; + + /** + * Sets the decorated flag. + */ + public function setDecorated(bool $decorated); + + /** + * Gets the decorated flag. + */ + public function isDecorated(): bool; + + public function setFormatter(OutputFormatterInterface $formatter); + + /** + * Returns current output formatter instance. + */ + public function getFormatter(): OutputFormatterInterface; +} diff --git a/cacme/vendor/symfony/console/Output/StreamOutput.php b/cacme/vendor/symfony/console/Output/StreamOutput.php new file mode 100644 index 0000000..ac58e41 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/StreamOutput.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\Console\Output; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * StreamOutput writes the output to a given stream. + * + * Usage: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * + * As `StreamOutput` can use any stream, you can also use a file: + * + * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); + * + * @author Fabien Potencier + */ +class StreamOutput extends Output +{ + private $stream; + + /** + * @param resource $stream A stream resource + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + * + * @throws InvalidArgumentException When first argument is not a real stream + */ + public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) + { + if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { + throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); + } + + $this->stream = $stream; + + if (null === $decorated) { + $decorated = $this->hasColorSupport(); + } + + parent::__construct($verbosity, $decorated, $formatter); + } + + /** + * Gets the stream attached to this StreamOutput instance. + * + * @return resource + */ + public function getStream() + { + return $this->stream; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + if ($newline) { + $message .= \PHP_EOL; + } + + @fwrite($this->stream, $message); + + fflush($this->stream); + } + + /** + * Returns true if the stream supports colorization. + * + * Colorization is disabled if not supported by the stream: + * + * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo + * terminals via named pipes, so we can only check the environment. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @return bool true if the stream supports colorization, false otherwise + */ + protected function hasColorSupport(): bool + { + // Follow https://no-color.org/ + if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { + return false; + } + + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + if (\DIRECTORY_SEPARATOR === '\\') { + return (\function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + return stream_isatty($this->stream); + } +} diff --git a/cacme/vendor/symfony/console/Output/TrimmedBufferOutput.php b/cacme/vendor/symfony/console/Output/TrimmedBufferOutput.php new file mode 100644 index 0000000..0d375e0 --- /dev/null +++ b/cacme/vendor/symfony/console/Output/TrimmedBufferOutput.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\Console\Output; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * A BufferedOutput that keeps only the last N chars. + * + * @author Jérémy Derussé + */ +class TrimmedBufferOutput extends Output +{ + private int $maxLength; + private string $buffer = ''; + + public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) + { + if ($maxLength <= 0) { + throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); + } + + parent::__construct($verbosity, $decorated, $formatter); + $this->maxLength = $maxLength; + } + + /** + * Empties buffer and returns its content. + */ + public function fetch(): string + { + $content = $this->buffer; + $this->buffer = ''; + + return $content; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + $this->buffer .= $message; + + if ($newline) { + $this->buffer .= \PHP_EOL; + } + + $this->buffer = substr($this->buffer, 0 - $this->maxLength); + } +} diff --git a/cacme/vendor/symfony/console/Question/ChoiceQuestion.php b/cacme/vendor/symfony/console/Question/ChoiceQuestion.php new file mode 100644 index 0000000..e449ff6 --- /dev/null +++ b/cacme/vendor/symfony/console/Question/ChoiceQuestion.php @@ -0,0 +1,177 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Represents a choice question. + * + * @author Fabien Potencier + */ +class ChoiceQuestion extends Question +{ + private array $choices; + private bool $multiselect = false; + private string $prompt = ' > '; + private string $errorMessage = 'Value "%s" is invalid'; + + /** + * @param string $question The question to ask to the user + * @param array $choices The list of available choices + * @param mixed $default The default answer to return + */ + public function __construct(string $question, array $choices, mixed $default = null) + { + if (!$choices) { + throw new \LogicException('Choice question must have at least 1 choice available.'); + } + + parent::__construct($question, $default); + + $this->choices = $choices; + $this->setValidator($this->getDefaultValidator()); + $this->setAutocompleterValues($choices); + } + + /** + * Returns available choices. + */ + public function getChoices(): array + { + return $this->choices; + } + + /** + * Sets multiselect option. + * + * When multiselect is set to true, multiple choices can be answered. + * + * @return $this + */ + public function setMultiselect(bool $multiselect): static + { + $this->multiselect = $multiselect; + $this->setValidator($this->getDefaultValidator()); + + return $this; + } + + /** + * Returns whether the choices are multiselect. + */ + public function isMultiselect(): bool + { + return $this->multiselect; + } + + /** + * Gets the prompt for choices. + */ + public function getPrompt(): string + { + return $this->prompt; + } + + /** + * Sets the prompt for choices. + * + * @return $this + */ + public function setPrompt(string $prompt): static + { + $this->prompt = $prompt; + + return $this; + } + + /** + * Sets the error message for invalid values. + * + * The error message has a string placeholder (%s) for the invalid value. + * + * @return $this + */ + public function setErrorMessage(string $errorMessage): static + { + $this->errorMessage = $errorMessage; + $this->setValidator($this->getDefaultValidator()); + + return $this; + } + + private function getDefaultValidator(): callable + { + $choices = $this->choices; + $errorMessage = $this->errorMessage; + $multiselect = $this->multiselect; + $isAssoc = $this->isAssoc($choices); + + return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { + if ($multiselect) { + // Check for a separated comma values + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) { + throw new InvalidArgumentException(sprintf($errorMessage, $selected)); + } + + $selectedChoices = explode(',', (string) $selected); + } else { + $selectedChoices = [$selected]; + } + + if ($this->isTrimmable()) { + foreach ($selectedChoices as $k => $v) { + $selectedChoices[$k] = trim((string) $v); + } + } + + $multiselectChoices = []; + foreach ($selectedChoices as $value) { + $results = []; + foreach ($choices as $key => $choice) { + if ($choice === $value) { + $results[] = $key; + } + } + + if (\count($results) > 1) { + throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results))); + } + + $result = array_search($value, $choices); + + if (!$isAssoc) { + if (false !== $result) { + $result = $choices[$result]; + } elseif (isset($choices[$value])) { + $result = $choices[$value]; + } + } elseif (false === $result && isset($choices[$value])) { + $result = $value; + } + + if (false === $result) { + throw new InvalidArgumentException(sprintf($errorMessage, $value)); + } + + // For associative choices, consistently return the key as string: + $multiselectChoices[] = $isAssoc ? (string) $result : $result; + } + + if ($multiselect) { + return $multiselectChoices; + } + + return current($multiselectChoices); + }; + } +} diff --git a/cacme/vendor/symfony/console/Question/ConfirmationQuestion.php b/cacme/vendor/symfony/console/Question/ConfirmationQuestion.php new file mode 100644 index 0000000..40eab24 --- /dev/null +++ b/cacme/vendor/symfony/console/Question/ConfirmationQuestion.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\Console\Question; + +/** + * Represents a yes/no question. + * + * @author Fabien Potencier + */ +class ConfirmationQuestion extends Question +{ + private string $trueAnswerRegex; + + /** + * @param string $question The question to ask to the user + * @param bool $default The default answer to return, true or false + * @param string $trueAnswerRegex A regex to match the "yes" answer + */ + public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i') + { + parent::__construct($question, $default); + + $this->trueAnswerRegex = $trueAnswerRegex; + $this->setNormalizer($this->getDefaultNormalizer()); + } + + /** + * Returns the default answer normalizer. + */ + private function getDefaultNormalizer(): callable + { + $default = $this->getDefault(); + $regex = $this->trueAnswerRegex; + + return function ($answer) use ($default, $regex) { + if (\is_bool($answer)) { + return $answer; + } + + $answerIsTrue = (bool) preg_match($regex, $answer); + if (false === $default) { + return $answer && $answerIsTrue; + } + + return '' === $answer || $answerIsTrue; + }; + } +} diff --git a/cacme/vendor/symfony/console/Question/Question.php b/cacme/vendor/symfony/console/Question/Question.php new file mode 100644 index 0000000..f99e685 --- /dev/null +++ b/cacme/vendor/symfony/console/Question/Question.php @@ -0,0 +1,283 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a Question. + * + * @author Fabien Potencier + */ +class Question +{ + private string $question; + private ?int $attempts = null; + private bool $hidden = false; + private bool $hiddenFallback = true; + private ?\Closure $autocompleterCallback = null; + private ?\Closure $validator = null; + private string|int|bool|null|float $default; + private ?\Closure $normalizer = null; + private bool $trimmable = true; + private bool $multiline = false; + + /** + * @param string $question The question to ask to the user + * @param string|bool|int|float|null $default The default answer to return if the user enters nothing + */ + public function __construct(string $question, string|bool|int|float $default = null) + { + $this->question = $question; + $this->default = $default; + } + + /** + * Returns the question. + */ + public function getQuestion(): string + { + return $this->question; + } + + /** + * Returns the default answer. + */ + public function getDefault(): string|bool|int|float|null + { + return $this->default; + } + + /** + * Returns whether the user response accepts newline characters. + */ + public function isMultiline(): bool + { + return $this->multiline; + } + + /** + * Sets whether the user response should accept newline characters. + * + * @return $this + */ + public function setMultiline(bool $multiline): static + { + $this->multiline = $multiline; + + return $this; + } + + /** + * Returns whether the user response must be hidden. + */ + public function isHidden(): bool + { + return $this->hidden; + } + + /** + * Sets whether the user response must be hidden or not. + * + * @return $this + * + * @throws LogicException In case the autocompleter is also used + */ + public function setHidden(bool $hidden): static + { + if ($this->autocompleterCallback) { + throw new LogicException('A hidden question cannot use the autocompleter.'); + } + + $this->hidden = $hidden; + + return $this; + } + + /** + * In case the response cannot be hidden, whether to fallback on non-hidden question or not. + */ + public function isHiddenFallback(): bool + { + return $this->hiddenFallback; + } + + /** + * Sets whether to fallback on non-hidden question if the response cannot be hidden. + * + * @return $this + */ + public function setHiddenFallback(bool $fallback): static + { + $this->hiddenFallback = $fallback; + + return $this; + } + + /** + * Gets values for the autocompleter. + */ + public function getAutocompleterValues(): ?iterable + { + $callback = $this->getAutocompleterCallback(); + + return $callback ? $callback('') : null; + } + + /** + * Sets values for the autocompleter. + * + * @return $this + * + * @throws LogicException + */ + public function setAutocompleterValues(?iterable $values): static + { + if (\is_array($values)) { + $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); + + $callback = static function () use ($values) { + return $values; + }; + } elseif ($values instanceof \Traversable) { + $valueCache = null; + $callback = static function () use ($values, &$valueCache) { + return $valueCache ?? $valueCache = iterator_to_array($values, false); + }; + } else { + $callback = null; + } + + return $this->setAutocompleterCallback($callback); + } + + /** + * Gets the callback function used for the autocompleter. + */ + public function getAutocompleterCallback(): ?callable + { + return $this->autocompleterCallback; + } + + /** + * Sets the callback function used for the autocompleter. + * + * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. + * + * @return $this + */ + public function setAutocompleterCallback(callable $callback = null): static + { + if ($this->hidden && null !== $callback) { + throw new LogicException('A hidden question cannot use the autocompleter.'); + } + + $this->autocompleterCallback = null === $callback || $callback instanceof \Closure ? $callback : \Closure::fromCallable($callback); + + return $this; + } + + /** + * Sets a validator for the question. + * + * @return $this + */ + public function setValidator(callable $validator = null): static + { + $this->validator = null === $validator || $validator instanceof \Closure ? $validator : \Closure::fromCallable($validator); + + return $this; + } + + /** + * Gets the validator for the question. + */ + public function getValidator(): ?callable + { + return $this->validator; + } + + /** + * Sets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + * + * @return $this + * + * @throws InvalidArgumentException in case the number of attempts is invalid + */ + public function setMaxAttempts(?int $attempts): static + { + if (null !== $attempts && $attempts < 1) { + throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); + } + + $this->attempts = $attempts; + + return $this; + } + + /** + * Gets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + */ + public function getMaxAttempts(): ?int + { + return $this->attempts; + } + + /** + * Sets a normalizer for the response. + * + * The normalizer can be a callable (a string), a closure or a class implementing __invoke. + * + * @return $this + */ + public function setNormalizer(callable $normalizer): static + { + $this->normalizer = $normalizer instanceof \Closure ? $normalizer : \Closure::fromCallable($normalizer); + + return $this; + } + + /** + * Gets the normalizer for the response. + * + * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. + */ + public function getNormalizer(): ?callable + { + return $this->normalizer; + } + + protected function isAssoc(array $array) + { + return (bool) \count(array_filter(array_keys($array), 'is_string')); + } + + public function isTrimmable(): bool + { + return $this->trimmable; + } + + /** + * @return $this + */ + public function setTrimmable(bool $trimmable): static + { + $this->trimmable = $trimmable; + + return $this; + } +} diff --git a/cacme/vendor/symfony/console/README.md b/cacme/vendor/symfony/console/README.md new file mode 100644 index 0000000..c4c1299 --- /dev/null +++ b/cacme/vendor/symfony/console/README.md @@ -0,0 +1,36 @@ +Console Component +================= + +The Console component eases the creation of beautiful and testable command line +interfaces. + +Sponsor +------- + +The Console component for Symfony 5.4/6.0 is [backed][1] by [Les-Tilleuls.coop][2]. + +Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and +fix your projects. We provide a wide range of professional services including development, +consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps. +We are a worker cooperative! + +Help Symfony by [sponsoring][3] its development! + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/console.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) + +Credits +------- + +`Resources/bin/hiddeninput.exe` is a third party binary provided within this +component. Find sources and license at https://github.com/Seldaek/hidden-input. + +[1]: https://symfony.com/backers +[2]: https://les-tilleuls.coop +[3]: https://symfony.com/sponsor diff --git a/cacme/vendor/symfony/console/Resources/bin/hiddeninput.exe b/cacme/vendor/symfony/console/Resources/bin/hiddeninput.exe new file mode 100644 index 0000000000000000000000000000000000000000..c8cf65e8d819e6e525121cf6b21f1c2429746038 GIT binary patch literal 9216 zcmeHNe{@sVeZR8hV88~S)=Hp|Mpn({rC^@)BwNOI{ERJXCYlx+k1K6PLHo z_e!z_fhOzeA3JTX&-Z@s{rFOgjEwBlqjr!)9f zjyHz`A+ni`!0Taby{Uj5Y>jQq(k5A+X})PLWAi|{IZbtc8n^^trM{GI=P_15U6d?l zJJ3PW8XjfHpR}6`k{&5@JcEeH_SqQoQbU62o2YS30W)p_t&Fjy*RXQCZt$gCf|ao| zx&3R}m6|-Lfi@pua=$26n(UlnWo$>K67*|+#(qL_An=?l0M02AhOSJDv3;~?1ORfw z76EdK#MpSHqACHLcnJLIYlCSiX4eS@Pr8rN)Xwz0dk7O*y^0_C(Yks2Kvg! z-d-fJ)F9@k?>)m(XqDKIe2OKfhCQde9fpO0ko24yn*4xzX7q+ze`Z*=aJgwV?D?73 zaJ8UkSk|NN>@-|mB*f`EIK7$ElgAB<7p&p`^Vuq$58#;?B^*Bz7&d$B#+AYUC z(^m|`7{lqx&b^5$;i`j|S!+u|lcaQplp_&Nb)!>r>vGh3wb!tW zLq6%bkSt8jO|(vWH>LiPV(Xkp%BiGhl1q!PXXNKVKE!>Y5cHc2%cJOJA{-&ZsSn`T z#8~TA#(HWH4m>uCd+kCMTFgMI*s*n3!iCOwEI`{vGcVhzDu!Lw%-Ea^JATtrF`q3`+#KvvYJ0vM~A}D#LOD zlw`4ncB0U*Jji=--Wz#>I&5?hy;MgYW2u91d8ob=7MWfY`u;7Xe-J{Qsb0=0p|SM2 zG|=~mERIj4?gi)Ew|{LIN#oAsh20k_khIYjJBBN6rrIJ=eQO=nE;rTnPSiaQS$1$# z+|JRh0!IbQIa*f1(TZ}QM;|WO0+jTy(e)ggN4>zqp2E>C>hGPLHjHBh--2%@{EZNE zbUk{<3MABX&20QwK{MxK8`1Vk>^%dO5i@VTfu>NG3$K4NC=hSPsj9UYy`rNO}sBnB9QdKdIk7G+2_amnWstdTYVg z7HgLJGC~XLZG`63GwH8PdO_+G(k6~?J8Wj5mQos#21kC4W#2)guQXI)!z^{@F)U)5 z*re+r(2dib3D4P~%Z6TL=$PIkpmm<_#isu%t=%DcIwNkJhMeJ|bpahHO%8h|y~Ccf zUg#xVk+dyu>Q1O7JZ~8KS>tqi0qK**X*y6yHM71`bT=kFZ=@E%oe2!Km1^2sa>v+onZ%x_>aOJF+N0{i~z|<(IzgT*{0PpQq}E zQpU35@bm;qI?t_znGI&5&4sZV>+%m}w$(4hSDvLk)l<{5XyMlnCl7C%AjM3XnWvVz z{NoFsX)JB)SoqABZxUa*Yq+^^(cbq4mL%^lO12c${z{pf+)|kTTI~nQywyYF6}6|8 zlsN9&{-vwTrTyu<5^90_AsIU-ID#ZG@6d%poU44<**%xVe?`uxf}_Mr$SLHLS|K_N zQnw>(Lr2U=%$-<2D~RSzbG)2W2u^KMDnFFE?GmmbQ)V)fty957F`4OvQ_25E68ITr z5?`suu`|v?r!y=gFOGj$%9IJ zuTP=&2GcnoZZ0qSe6YL-*-lg>Q#>?Ew`a=GDc4vI#<1sNdKn?n7iSj0Orl$-#FMFi zykr>X-Xvi>sVr;92+8*H!r|3L$#o~hXa0z>AmF=z z?|@FF;*S|S0yqsw0j>Z(3mX-HD!|{N-vYc9paC8Ld=|6?00!6(_%lERupO`&um*4k z0b~W>e*uhTe4;V;mq>(ox$9FB`wLt!*DKj~!aOh|fL&#Pg*b??tm%5~_6M#02wqeC zS~wO>TWGnSp^r<0&8f2V6W->w=C+p~daC5e5wNQM*(* z66^}b0(!q3)zq$mu&VnbR#nr3;h5DS*o7{y66=!#;Dy4$pd1ZH<6WEOi0oJ8SxRL* z*v-9@Z^2w%^S(w5dO{_9Duby%2RT~;ppxaE$l()x6&}>7Wcg=u_&>f`Vs8OJGTy{X z2HpG=ThJz<{%|4Qq-~ad0qcrc87n88DHpM(nypwXIkZn<{zIT$ul&BQ?{ApCAZtyr zs2YpNt@x(G*faTU*HCKnAk(G=Tl~>r1QK8LY~J8mFFGoN5iIkYSwlm4Lsj#g4dsE5 zU-4;*Kdh-zv!rT4N$O}Q&n)?v0-9Y)lRFz58^P-KtKonzrfQ1p@0V_10^0||cGRn9 zRG<-#_TEV2nn4{BOh{YVBR4e!V!D?0K%BAlQN!D%M#k1bHypiIHT)5tlj>p0Pp_;+ z!cqC-JIs@JRhB+#teGs$Cib_=(yjRo4OJg^YPg%58aJVsC(LQ?W6%pn!-#aMZwoPcopo^Rn6BE z3=c5&W5~pP(C(-2r;PnH-S0{F`runM0ERCf3rESX$+S(MKOXmKJL9zXF}9-lf^xUs z+bb)+P%L&gV@<4q{6w^xEJ>Y>TQFUeoz0o-yq)jUqww=?wjUO8Y{a5G;DJ0Jr!LL+ zWhgsLuzi&eDrGDn$2DJwpFfH-?SGWbr>qRb?v{P`_%)So)CQgzO^HQ%;y#tJ=knH4 z95jX;^bF#BiuTH^%-j}{9VrZD=R%Q%wselH^p>5 z7d>gWB-st&3Fj%Mt*|tR5iK3J=`xhs&G)I7E>`FO@o7L z@S$B!pYMuzz5DN@X!O4DPm5n@raPJn-Q#o*m*e^5lk$g?0esg%$;>g5QW-|;c=H2GM}bo2tW^D924wmOkrUbWxcQ# z#v6bP%Tdfe~jtCRzAL;-OahZ=#yvUixu2-9fD2j$*|YY`F?0wF-{a# ztr<&kZjZ+81}6ZESqtgW)8kP#s@VLTSUR{}6?U^R*x7RE3Rl&n=VnFFqg9Uqz1n@N9N|=9<4} zuJfy^+}|D9X&vm3MAdqmu0&UMd^=K>b1hLAm_E!$rZC2b;;T~Dl zI`Eo_yRY76uM})|6wk9->of(=9&4jLv5#p@OzS~Yl>@pG)^>6`R+KtL{<4ly4o9WiM!%p_pfROU354)e8PIeE z1_s?#;OX6waNvvb&UQRN(WLbR+}&b#jo&WY-LlwCX}Q*$jGuKYuOGoIoyR(>e}}ix z+t}Q^cEcC8Y{@h}>HmJ^gD!l@gzwHmiBKl26x_lZVZG2UY!`w;RJd122;US&geQdW z3Qq}R!gIo5;ka;0I4c-Jq5X6A6?VzK&c4y!ZXdAUYu{r}*!SBXw?Aor+J4-A(*COb zb^CwV-?3k`zi-cX*c`VzL`RLI(b4MgIrGN z%ojf`E*6)Gg1A9!7q^N##2zsss^V9~-Qt7d!{UDNZ^XY9pA^3@9ui*?e=7c5d`nD; z?}~R(p>y1Kw!>|X4ycYEAkcZa*n-R%y! zqi)Up756UpqwfE7=hfigw$k~G@25gaxF9UGTkV>C(7x1Rbx4jb#|}rxq0vQ!n-c#f J0sQ~1{4brj`U(I5 literal 0 HcmV?d00001 diff --git a/cacme/vendor/symfony/console/Resources/completion.bash b/cacme/vendor/symfony/console/Resources/completion.bash new file mode 100644 index 0000000..64b87cc --- /dev/null +++ b/cacme/vendor/symfony/console/Resources/completion.bash @@ -0,0 +1,84 @@ +# This file is part of the Symfony package. +# +# (c) Fabien Potencier +# +# For the full copyright and license information, please view +# https://symfony.com/doc/current/contributing/code/license.html + +_sf_{{ COMMAND_NAME }}() { + # Use newline as only separator to allow space in completion values + IFS=$'\n' + local sf_cmd="${COMP_WORDS[0]}" + + # for an alias, get the real script behind it + sf_cmd_type=$(type -t $sf_cmd) + if [[ $sf_cmd_type == "alias" ]]; then + sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/") + elif [[ $sf_cmd_type == "file" ]]; then + sf_cmd=$(type -p $sf_cmd) + fi + + if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then + return 1 + fi + + local cur prev words cword + _get_comp_words_by_ref -n := cur prev words cword + + local completecmd=("$sf_cmd" "_complete" "--no-interaction" "-sbash" "-c$cword" "-S{{ VERSION }}") + for w in ${words[@]}; do + w=$(printf -- '%b' "$w") + # remove quotes from typed values + quote="${w:0:1}" + if [ "$quote" == \' ]; then + w="${w%\'}" + w="${w#\'}" + elif [ "$quote" == \" ]; then + w="${w%\"}" + w="${w#\"}" + fi + # empty values are ignored + if [ ! -z "$w" ]; then + completecmd+=("-i$w") + fi + done + + local sfcomplete + if sfcomplete=$(${completecmd[@]} 2>&1); then + local quote suggestions + quote=${cur:0:1} + + # Use single quotes by default if suggestions contains backslash (FQCN) + if [ "$quote" == '' ] && [[ "$sfcomplete" =~ \\ ]]; then + quote=\' + fi + + if [ "$quote" == \' ]; then + # single quotes: no additional escaping (does not accept ' in values) + suggestions=$(for s in $sfcomplete; do printf $'%q%q%q\n' "$quote" "$s" "$quote"; done) + elif [ "$quote" == \" ]; then + # double quotes: double escaping for \ $ ` " + suggestions=$(for s in $sfcomplete; do + s=${s//\\/\\\\} + s=${s//\$/\\\$} + s=${s//\`/\\\`} + s=${s//\"/\\\"} + printf $'%q%q%q\n' "$quote" "$s" "$quote"; + done) + else + # no quotes: double escaping + suggestions=$(for s in $sfcomplete; do printf $'%q\n' $(printf '%q' "$s"); done) + fi + COMPREPLY=($(IFS=$'\n' compgen -W "$suggestions" -- $(printf -- "%q" "$cur"))) + __ltrim_colon_completions "$cur" + else + if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then + >&2 echo + >&2 echo $sfcomplete + fi + + return 1 + fi +} + +complete -F _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }} diff --git a/cacme/vendor/symfony/console/SignalRegistry/SignalRegistry.php b/cacme/vendor/symfony/console/SignalRegistry/SignalRegistry.php new file mode 100644 index 0000000..f51c0c3 --- /dev/null +++ b/cacme/vendor/symfony/console/SignalRegistry/SignalRegistry.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\Console\SignalRegistry; + +final class SignalRegistry +{ + private array $signalHandlers = []; + + public function __construct() + { + if (\function_exists('pcntl_async_signals')) { + pcntl_async_signals(true); + } + } + + public function register(int $signal, callable $signalHandler): void + { + if (!isset($this->signalHandlers[$signal])) { + $previousCallback = pcntl_signal_get_handler($signal); + + if (\is_callable($previousCallback)) { + $this->signalHandlers[$signal][] = $previousCallback; + } + } + + $this->signalHandlers[$signal][] = $signalHandler; + + pcntl_signal($signal, [$this, 'handle']); + } + + public static function isSupported(): bool + { + if (!\function_exists('pcntl_signal')) { + return false; + } + + if (\in_array('pcntl_signal', explode(',', \ini_get('disable_functions')))) { + return false; + } + + return true; + } + + /** + * @internal + */ + public function handle(int $signal): void + { + $count = \count($this->signalHandlers[$signal]); + + foreach ($this->signalHandlers[$signal] as $i => $signalHandler) { + $hasNext = $i !== $count - 1; + $signalHandler($signal, $hasNext); + } + } +} diff --git a/cacme/vendor/symfony/console/SingleCommandApplication.php b/cacme/vendor/symfony/console/SingleCommandApplication.php new file mode 100644 index 0000000..4f0b5ba --- /dev/null +++ b/cacme/vendor/symfony/console/SingleCommandApplication.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\Console; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Grégoire Pineau + */ +class SingleCommandApplication extends Command +{ + private string $version = 'UNKNOWN'; + private bool $autoExit = true; + private bool $running = false; + + /** + * @return $this + */ + public function setVersion(string $version): static + { + $this->version = $version; + + return $this; + } + + /** + * @final + * + * @return $this + */ + public function setAutoExit(bool $autoExit): static + { + $this->autoExit = $autoExit; + + return $this; + } + + public function run(InputInterface $input = null, OutputInterface $output = null): int + { + if ($this->running) { + return parent::run($input, $output); + } + + // We use the command name as the application name + $application = new Application($this->getName() ?: 'UNKNOWN', $this->version); + $application->setAutoExit($this->autoExit); + // Fix the usage of the command displayed with "--help" + $this->setName($_SERVER['argv'][0]); + $application->add($this); + $application->setDefaultCommand($this->getName(), true); + + $this->running = true; + try { + $ret = $application->run($input, $output); + } finally { + $this->running = false; + } + + return $ret ?? 1; + } +} diff --git a/cacme/vendor/symfony/console/Style/OutputStyle.php b/cacme/vendor/symfony/console/Style/OutputStyle.php new file mode 100644 index 0000000..0b2ded3 --- /dev/null +++ b/cacme/vendor/symfony/console/Style/OutputStyle.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 Symfony\Component\Console\Style; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Decorates output to add console style guide helpers. + * + * @author Kevin Bond + */ +abstract class OutputStyle implements OutputInterface, StyleInterface +{ + private $output; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + } + + /** + * {@inheritdoc} + */ + public function newLine(int $count = 1) + { + $this->output->write(str_repeat(\PHP_EOL, $count)); + } + + public function createProgressBar(int $max = 0): ProgressBar + { + return new ProgressBar($this->output, $max); + } + + /** + * {@inheritdoc} + */ + public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) + { + $this->output->write($messages, $newline, $type); + } + + /** + * {@inheritdoc} + */ + public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL) + { + $this->output->writeln($messages, $type); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + $this->output->setVerbosity($level); + } + + /** + * {@inheritdoc} + */ + public function getVerbosity(): int + { + return $this->output->getVerbosity(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + $this->output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function isDecorated(): bool + { + return $this->output->isDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + $this->output->setFormatter($formatter); + } + + /** + * {@inheritdoc} + */ + public function getFormatter(): OutputFormatterInterface + { + return $this->output->getFormatter(); + } + + /** + * {@inheritdoc} + */ + public function isQuiet(): bool + { + return $this->output->isQuiet(); + } + + /** + * {@inheritdoc} + */ + public function isVerbose(): bool + { + return $this->output->isVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose(): bool + { + return $this->output->isVeryVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isDebug(): bool + { + return $this->output->isDebug(); + } + + protected function getErrorOutput() + { + if (!$this->output instanceof ConsoleOutputInterface) { + return $this->output; + } + + return $this->output->getErrorOutput(); + } +} diff --git a/cacme/vendor/symfony/console/Style/StyleInterface.php b/cacme/vendor/symfony/console/Style/StyleInterface.php new file mode 100644 index 0000000..0bb1233 --- /dev/null +++ b/cacme/vendor/symfony/console/Style/StyleInterface.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\Console\Style; + +/** + * Output style helpers. + * + * @author Kevin Bond + */ +interface StyleInterface +{ + /** + * Formats a command title. + */ + public function title(string $message); + + /** + * Formats a section title. + */ + public function section(string $message); + + /** + * Formats a list. + */ + public function listing(array $elements); + + /** + * Formats informational text. + */ + public function text(string|array $message); + + /** + * Formats a success result bar. + */ + public function success(string|array $message); + + /** + * Formats an error result bar. + */ + public function error(string|array $message); + + /** + * Formats an warning result bar. + */ + public function warning(string|array $message); + + /** + * Formats a note admonition. + */ + public function note(string|array $message); + + /** + * Formats a caution admonition. + */ + public function caution(string|array $message); + + /** + * Formats a table. + */ + public function table(array $headers, array $rows); + + /** + * Asks a question. + */ + public function ask(string $question, string $default = null, callable $validator = null): mixed; + + /** + * Asks a question with the user input hidden. + */ + public function askHidden(string $question, callable $validator = null): mixed; + + /** + * Asks for confirmation. + */ + public function confirm(string $question, bool $default = true): bool; + + /** + * Asks a choice question. + */ + public function choice(string $question, array $choices, mixed $default = null): mixed; + + /** + * Add newline(s). + */ + public function newLine(int $count = 1); + + /** + * Starts the progress output. + */ + public function progressStart(int $max = 0); + + /** + * Advances the progress output X steps. + */ + public function progressAdvance(int $step = 1); + + /** + * Finishes the progress output. + */ + public function progressFinish(); +} diff --git a/cacme/vendor/symfony/console/Style/SymfonyStyle.php b/cacme/vendor/symfony/console/Style/SymfonyStyle.php new file mode 100644 index 0000000..2730242 --- /dev/null +++ b/cacme/vendor/symfony/console/Style/SymfonyStyle.php @@ -0,0 +1,500 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Helper\SymfonyQuestionHelper; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableSeparator; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\TrimmedBufferOutput; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +/** + * Output decorator helpers for the Symfony Style Guide. + * + * @author Kevin Bond + */ +class SymfonyStyle extends OutputStyle +{ + public const MAX_LINE_LENGTH = 120; + + private $input; + private $output; + private $questionHelper; + private $progressBar; + private int $lineLength; + private $bufferedOutput; + + public function __construct(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter()); + // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. + $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; + $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); + + parent::__construct($this->output = $output); + } + + /** + * Formats a message as a block of text. + */ + public function block(string|array $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) + { + $messages = \is_array($messages) ? array_values($messages) : [$messages]; + + $this->autoPrependBlock(); + $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function title(string $message) + { + $this->autoPrependBlock(); + $this->writeln([ + sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + sprintf('%s', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function section(string $message) + { + $this->autoPrependBlock(); + $this->writeln([ + sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + sprintf('%s', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function listing(array $elements) + { + $this->autoPrependText(); + $elements = array_map(function ($element) { + return sprintf(' * %s', $element); + }, $elements); + + $this->writeln($elements); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function text(string|array $message) + { + $this->autoPrependText(); + + $messages = \is_array($message) ? array_values($message) : [$message]; + foreach ($messages as $message) { + $this->writeln(sprintf(' %s', $message)); + } + } + + /** + * Formats a command comment. + */ + public function comment(string|array $message) + { + $this->block($message, null, null, ' // ', false, false); + } + + /** + * {@inheritdoc} + */ + public function success(string|array $message) + { + $this->block($message, 'OK', 'fg=black;bg=green', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function error(string|array $message) + { + $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function warning(string|array $message) + { + $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function note(string|array $message) + { + $this->block($message, 'NOTE', 'fg=yellow', ' ! '); + } + + /** + * Formats an info message. + */ + public function info(string|array $message) + { + $this->block($message, 'INFO', 'fg=green', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function caution(string|array $message) + { + $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true); + } + + /** + * {@inheritdoc} + */ + public function table(array $headers, array $rows) + { + $this->createTable() + ->setHeaders($headers) + ->setRows($rows) + ->render() + ; + + $this->newLine(); + } + + /** + * Formats a horizontal table. + */ + public function horizontalTable(array $headers, array $rows) + { + $this->createTable() + ->setHorizontal(true) + ->setHeaders($headers) + ->setRows($rows) + ->render() + ; + + $this->newLine(); + } + + /** + * Formats a list of key/value horizontally. + * + * Each row can be one of: + * * 'A title' + * * ['key' => 'value'] + * * new TableSeparator() + */ + public function definitionList(string|array|TableSeparator ...$list) + { + $headers = []; + $row = []; + foreach ($list as $value) { + if ($value instanceof TableSeparator) { + $headers[] = $value; + $row[] = $value; + continue; + } + if (\is_string($value)) { + $headers[] = new TableCell($value, ['colspan' => 2]); + $row[] = null; + continue; + } + if (!\is_array($value)) { + throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); + } + $headers[] = key($value); + $row[] = current($value); + } + + $this->horizontalTable($headers, [$row]); + } + + /** + * {@inheritdoc} + */ + public function ask(string $question, string $default = null, callable $validator = null): mixed + { + $question = new Question($question, $default); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function askHidden(string $question, callable $validator = null): mixed + { + $question = new Question($question); + + $question->setHidden(true); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function confirm(string $question, bool $default = true): bool + { + return $this->askQuestion(new ConfirmationQuestion($question, $default)); + } + + /** + * {@inheritdoc} + */ + public function choice(string $question, array $choices, mixed $default = null): mixed + { + if (null !== $default) { + $values = array_flip($choices); + $default = $values[$default] ?? $default; + } + + return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); + } + + /** + * {@inheritdoc} + */ + public function progressStart(int $max = 0) + { + $this->progressBar = $this->createProgressBar($max); + $this->progressBar->start(); + } + + /** + * {@inheritdoc} + */ + public function progressAdvance(int $step = 1) + { + $this->getProgressBar()->advance($step); + } + + /** + * {@inheritdoc} + */ + public function progressFinish() + { + $this->getProgressBar()->finish(); + $this->newLine(2); + unset($this->progressBar); + } + + /** + * {@inheritdoc} + */ + public function createProgressBar(int $max = 0): ProgressBar + { + $progressBar = parent::createProgressBar($max); + + if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) { + $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 + $progressBar->setProgressCharacter(''); + $progressBar->setBarCharacter('▓'); // dark shade character \u2593 + } + + return $progressBar; + } + + /** + * @see ProgressBar::iterate() + */ + public function progressIterate(iterable $iterable, int $max = null): iterable + { + yield from $this->createProgressBar()->iterate($iterable, $max); + + $this->newLine(2); + } + + public function askQuestion(Question $question): mixed + { + if ($this->input->isInteractive()) { + $this->autoPrependBlock(); + } + + $this->questionHelper ??= new SymfonyQuestionHelper(); + + $answer = $this->questionHelper->ask($this->input, $this, $question); + + if ($this->input->isInteractive()) { + $this->newLine(); + $this->bufferedOutput->write("\n"); + } + + return $answer; + } + + /** + * {@inheritdoc} + */ + public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL) + { + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + foreach ($messages as $message) { + parent::writeln($message, $type); + $this->writeBuffer($message, true, $type); + } + } + + /** + * {@inheritdoc} + */ + public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) + { + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + foreach ($messages as $message) { + parent::write($message, $newline, $type); + $this->writeBuffer($message, $newline, $type); + } + } + + /** + * {@inheritdoc} + */ + public function newLine(int $count = 1) + { + parent::newLine($count); + $this->bufferedOutput->write(str_repeat("\n", $count)); + } + + /** + * Returns a new instance which makes use of stderr if available. + */ + public function getErrorStyle(): self + { + return new self($this->input, $this->getErrorOutput()); + } + + public function createTable(): Table + { + $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output; + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + return (new Table($output))->setStyle($style); + } + + private function getProgressBar(): ProgressBar + { + return $this->progressBar + ?? throw new RuntimeException('The ProgressBar is not started.'); + } + + private function autoPrependBlock(): void + { + $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); + + if (!isset($chars[0])) { + $this->newLine(); // empty history, so we should start with a new line. + + return; + } + // Prepend new line for each non LF chars (This means no blank line was output before) + $this->newLine(2 - substr_count($chars, "\n")); + } + + private function autoPrependText(): void + { + $fetched = $this->bufferedOutput->fetch(); + // Prepend new line if last char isn't EOL: + if (!str_ends_with($fetched, "\n")) { + $this->newLine(); + } + } + + private function writeBuffer(string $message, bool $newLine, int $type): void + { + // We need to know if the last chars are PHP_EOL + $this->bufferedOutput->write($message, $newLine, $type); + } + + private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array + { + $indentLength = 0; + $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix)); + $lines = []; + + if (null !== $type) { + $type = sprintf('[%s] ', $type); + $indentLength = \strlen($type); + $lineIndentation = str_repeat(' ', $indentLength); + } + + // wrap and add newlines for each element + foreach ($messages as $key => $message) { + if ($escape) { + $message = OutputFormatter::escape($message); + } + + $decorationLength = Helper::width($message) - Helper::width(Helper::removeDecoration($this->getFormatter(), $message)); + $messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength); + $messageLines = explode(\PHP_EOL, wordwrap($message, $messageLineLength, \PHP_EOL, true)); + foreach ($messageLines as $messageLine) { + $lines[] = $messageLine; + } + + if (\count($messages) > 1 && $key < \count($messages) - 1) { + $lines[] = ''; + } + } + + $firstLineIndex = 0; + if ($padding && $this->isDecorated()) { + $firstLineIndex = 1; + array_unshift($lines, ''); + $lines[] = ''; + } + + foreach ($lines as $i => &$line) { + if (null !== $type) { + $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line; + } + + $line = $prefix.$line; + $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0)); + + if ($style) { + $line = sprintf('<%s>%s', $style, $line); + } + } + + return $lines; + } +} diff --git a/cacme/vendor/symfony/console/Terminal.php b/cacme/vendor/symfony/console/Terminal.php new file mode 100644 index 0000000..80020c9 --- /dev/null +++ b/cacme/vendor/symfony/console/Terminal.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +class Terminal +{ + private static ?int $width = null; + private static ?int $height = null; + private static ?bool $stty = null; + + /** + * Gets the terminal width. + */ + public function getWidth(): int + { + $width = getenv('COLUMNS'); + if (false !== $width) { + return (int) trim($width); + } + + if (null === self::$width) { + self::initDimensions(); + } + + return self::$width ?: 80; + } + + /** + * Gets the terminal height. + */ + public function getHeight(): int + { + $height = getenv('LINES'); + if (false !== $height) { + return (int) trim($height); + } + + if (null === self::$height) { + self::initDimensions(); + } + + return self::$height ?: 50; + } + + /** + * @internal + */ + public static function hasSttyAvailable(): bool + { + if (null !== self::$stty) { + return self::$stty; + } + + // skip check if exec function is disabled + if (!\function_exists('exec')) { + return false; + } + + exec('stty 2>&1', $output, $exitcode); + + return self::$stty = 0 === $exitcode; + } + + private static function initDimensions() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { + // extract [w, H] from "wxh (WxH)" + // or [w, h] from "wxh" + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) + // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT + self::initDimensionsUsingStty(); + } elseif (null !== $dimensions = self::getConsoleMode()) { + // extract [w, h] from "wxh" + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; + } + } else { + self::initDimensionsUsingStty(); + } + } + + /** + * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). + */ + private static function hasVt100Support(): bool + { + return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w')); + } + + /** + * Initializes dimensions using the output of an stty columns line. + */ + private static function initDimensionsUsingStty() + { + if ($sttyString = self::getSttyColumns()) { + if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { + // extract [w, h] from "rows h; columns w;" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { + // extract [w, h] from "; h rows; w columns" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } + } + } + + /** + * Runs and parses mode CON if it's available, suppressing any error output. + * + * @return int[]|null An array composed of the width and the height or null if it could not be parsed + */ + private static function getConsoleMode(): ?array + { + $info = self::readFromProcess('mode CON'); + + if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + return null; + } + + return [(int) $matches[2], (int) $matches[1]]; + } + + /** + * Runs and parses stty -a if it's available, suppressing any error output. + */ + private static function getSttyColumns(): ?string + { + return self::readFromProcess('stty -a | grep columns'); + } + + private static function readFromProcess(string $command): ?string + { + if (!\function_exists('proc_open')) { + return null; + } + + $descriptorspec = [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); + if (!\is_resource($process)) { + return null; + } + + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + return $info; + } +} diff --git a/cacme/vendor/symfony/console/Tester/ApplicationTester.php b/cacme/vendor/symfony/console/Tester/ApplicationTester.php new file mode 100644 index 0000000..275a305 --- /dev/null +++ b/cacme/vendor/symfony/console/Tester/ApplicationTester.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\Console\Tester; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\ArrayInput; + +/** + * Eases the testing of console applications. + * + * When testing an application, don't forget to disable the auto exit flag: + * + * $application = new Application(); + * $application->setAutoExit(false); + * + * @author Fabien Potencier + */ +class ApplicationTester +{ + use TesterTrait; + + private $application; + + public function __construct(Application $application) + { + $this->application = $application; + } + + /** + * Executes the application. + * + * Available options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + * + * @return int The command exit code + */ + public function run(array $input, array $options = []): int + { + $prevShellVerbosity = getenv('SHELL_VERBOSITY'); + + try { + $this->input = new ArrayInput($input); + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + if ($this->inputs) { + $this->input->setStream(self::createStream($this->inputs)); + } + + $this->initOutput($options); + + return $this->statusCode = $this->application->run($this->input, $this->output); + } finally { + // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it + // to its previous value to avoid one test's verbosity to spread to the following tests + if (false === $prevShellVerbosity) { + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY'); + } + unset($_ENV['SHELL_VERBOSITY']); + unset($_SERVER['SHELL_VERBOSITY']); + } else { + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY='.$prevShellVerbosity); + } + $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity; + } + } + } +} diff --git a/cacme/vendor/symfony/console/Tester/CommandCompletionTester.php b/cacme/vendor/symfony/console/Tester/CommandCompletionTester.php new file mode 100644 index 0000000..ade7327 --- /dev/null +++ b/cacme/vendor/symfony/console/Tester/CommandCompletionTester.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\Console\Tester; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; + +/** + * Eases the testing of command completion. + * + * @author Jérôme Tamarelle + */ +class CommandCompletionTester +{ + private $command; + + public function __construct(Command $command) + { + $this->command = $command; + } + + /** + * Create completion suggestions from input tokens. + */ + public function complete(array $input): array + { + $currentIndex = \count($input); + if ('' === end($input)) { + array_pop($input); + } + array_unshift($input, $this->command->getName()); + + $completionInput = CompletionInput::fromTokens($input, $currentIndex); + $completionInput->bind($this->command->getDefinition()); + $suggestions = new CompletionSuggestions(); + + $this->command->complete($completionInput, $suggestions); + + $options = []; + foreach ($suggestions->getOptionSuggestions() as $option) { + $options[] = '--'.$option->getName(); + } + + return array_map('strval', array_merge($options, $suggestions->getValueSuggestions())); + } +} diff --git a/cacme/vendor/symfony/console/Tester/CommandTester.php b/cacme/vendor/symfony/console/Tester/CommandTester.php new file mode 100644 index 0000000..f6ee4b7 --- /dev/null +++ b/cacme/vendor/symfony/console/Tester/CommandTester.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\Console\Tester; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArrayInput; + +/** + * Eases the testing of console commands. + * + * @author Fabien Potencier + * @author Robin Chalas + */ +class CommandTester +{ + use TesterTrait; + + private $command; + + public function __construct(Command $command) + { + $this->command = $command; + } + + /** + * Executes the command. + * + * Available execution options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + * + * @param array $input An array of command arguments and options + * @param array $options An array of execution options + * + * @return int The command exit code + */ + public function execute(array $input, array $options = []): int + { + // set the command name automatically if the application requires + // this argument and no command name was passed + if (!isset($input['command']) + && (null !== $application = $this->command->getApplication()) + && $application->getDefinition()->hasArgument('command') + ) { + $input = array_merge(['command' => $this->command->getName()], $input); + } + + $this->input = new ArrayInput($input); + // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. + $this->input->setStream(self::createStream($this->inputs)); + + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + if (!isset($options['decorated'])) { + $options['decorated'] = false; + } + + $this->initOutput($options); + + return $this->statusCode = $this->command->run($this->input, $this->output); + } +} diff --git a/cacme/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php b/cacme/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php new file mode 100644 index 0000000..a473242 --- /dev/null +++ b/cacme/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.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\Console\Tester\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\Console\Command\Command; + +final class CommandIsSuccessful extends Constraint +{ + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'is successful'; + } + + /** + * {@inheritdoc} + */ + protected function matches($other): bool + { + return Command::SUCCESS === $other; + } + + /** + * {@inheritdoc} + */ + protected function failureDescription($other): string + { + return 'the command '.$this->toString(); + } + + /** + * {@inheritdoc} + */ + protected function additionalFailureDescription($other): string + { + $mapping = [ + Command::FAILURE => 'Command failed.', + Command::INVALID => 'Command was invalid.', + ]; + + return $mapping[$other] ?? sprintf('Command returned exit status %d.', $other); + } +} diff --git a/cacme/vendor/symfony/console/Tester/TesterTrait.php b/cacme/vendor/symfony/console/Tester/TesterTrait.php new file mode 100644 index 0000000..b238f95 --- /dev/null +++ b/cacme/vendor/symfony/console/Tester/TesterTrait.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 Symfony\Component\Console\Tester; + +use PHPUnit\Framework\Assert; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; +use Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful; + +/** + * @author Amrouche Hamza + */ +trait TesterTrait +{ + private $output; + private array $inputs = []; + private bool $captureStreamsIndependently = false; + private $input; + private int $statusCode; + + /** + * Gets the display returned by the last execution of the command or application. + * + * @throws \RuntimeException If it's called before the execute method + */ + public function getDisplay(bool $normalize = false): string + { + if (!isset($this->output)) { + throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); + } + + rewind($this->output->getStream()); + + $display = stream_get_contents($this->output->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the output written to STDERR by the application. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + */ + public function getErrorOutput(bool $normalize = false): string + { + if (!$this->captureStreamsIndependently) { + throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); + } + + rewind($this->output->getErrorOutput()->getStream()); + + $display = stream_get_contents($this->output->getErrorOutput()->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the input instance used by the last execution of the command or application. + */ + public function getInput(): InputInterface + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the command or application. + */ + public function getOutput(): OutputInterface + { + return $this->output; + } + + /** + * Gets the status code returned by the last execution of the command or application. + * + * @throws \RuntimeException If it's called before the execute method + */ + public function getStatusCode(): int + { + return $this->statusCode ?? throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?'); + } + + public function assertCommandIsSuccessful(string $message = ''): void + { + Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message); + } + + /** + * Sets the user inputs. + * + * @param array $inputs An array of strings representing each input + * passed to the command input stream + * + * @return $this + */ + public function setInputs(array $inputs): static + { + $this->inputs = $inputs; + + return $this; + } + + /** + * Initializes the output property. + * + * Available options: + * + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + */ + private function initOutput(array $options) + { + $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; + if (!$this->captureStreamsIndependently) { + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + if (isset($options['decorated'])) { + $this->output->setDecorated($options['decorated']); + } + if (isset($options['verbosity'])) { + $this->output->setVerbosity($options['verbosity']); + } + } else { + $this->output = new ConsoleOutput( + $options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, + $options['decorated'] ?? null + ); + + $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); + $errorOutput->setFormatter($this->output->getFormatter()); + $errorOutput->setVerbosity($this->output->getVerbosity()); + $errorOutput->setDecorated($this->output->isDecorated()); + + $reflectedOutput = new \ReflectionObject($this->output); + $strErrProperty = $reflectedOutput->getProperty('stderr'); + $strErrProperty->setAccessible(true); + $strErrProperty->setValue($this->output, $errorOutput); + + $reflectedParent = $reflectedOutput->getParentClass(); + $streamProperty = $reflectedParent->getProperty('stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); + } + } + + /** + * @return resource + */ + private static function createStream(array $inputs) + { + $stream = fopen('php://memory', 'r+', false); + + foreach ($inputs as $input) { + fwrite($stream, $input.\PHP_EOL); + } + + rewind($stream); + + return $stream; + } +} diff --git a/cacme/vendor/symfony/console/composer.json b/cacme/vendor/symfony/console/composer.json new file mode 100644 index 0000000..7d3947f --- /dev/null +++ b/cacme/vendor/symfony/console/composer.json @@ -0,0 +1,56 @@ +{ + "name": "symfony/console", + "type": "library", + "description": "Eases the creation of beautiful and testable command line interfaces", + "keywords": ["console", "cli", "command line", "terminal"], + "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.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0", + "psr/log": "^1|^2|^3" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "suggest": { + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "", + "psr/log": "For using the console logger" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Console\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/cacme/vendor/symfony/deprecation-contracts/.gitignore b/cacme/vendor/symfony/deprecation-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/cacme/vendor/symfony/deprecation-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/cacme/vendor/symfony/deprecation-contracts/CHANGELOG.md b/cacme/vendor/symfony/deprecation-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/cacme/vendor/symfony/deprecation-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/cacme/vendor/symfony/deprecation-contracts/LICENSE b/cacme/vendor/symfony/deprecation-contracts/LICENSE new file mode 100644 index 0000000..406242f --- /dev/null +++ b/cacme/vendor/symfony/deprecation-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-2022 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +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/cacme/vendor/symfony/deprecation-contracts/README.md b/cacme/vendor/symfony/deprecation-contracts/README.md new file mode 100644 index 0000000..4957933 --- /dev/null +++ b/cacme/vendor/symfony/deprecation-contracts/README.md @@ -0,0 +1,26 @@ +Symfony Deprecation Contracts +============================= + +A generic function and convention to trigger deprecation notices. + +This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. + +By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, +the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. + +The function requires at least 3 arguments: + - the name of the Composer package that is triggering the deprecation + - the version of the package that introduced the deprecation + - the message of the deprecation + - more arguments can be provided: they will be inserted in the message using `printf()` formatting + +Example: +```php +trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); +``` + +This will generate the following message: +`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` + +While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty +`function trigger_deprecation() {}` in your application. diff --git a/cacme/vendor/symfony/deprecation-contracts/composer.json b/cacme/vendor/symfony/deprecation-contracts/composer.json new file mode 100644 index 0000000..1c1b4ba --- /dev/null +++ b/cacme/vendor/symfony/deprecation-contracts/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/deprecation-contracts", + "type": "library", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.0.2" + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/cacme/vendor/symfony/deprecation-contracts/function.php b/cacme/vendor/symfony/deprecation-contracts/function.php new file mode 100644 index 0000000..2d56512 --- /dev/null +++ b/cacme/vendor/symfony/deprecation-contracts/function.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!function_exists('trigger_deprecation')) { + /** + * Triggers a silenced deprecation notice. + * + * @param string $package The name of the Composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string $message The message of the deprecation + * @param mixed ...$args Values to insert in the message using printf() formatting + * + * @author Nicolas Grekas + */ + function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void + { + @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); + } +} diff --git a/cacme/vendor/symfony/polyfill-ctype/Ctype.php b/cacme/vendor/symfony/polyfill-ctype/Ctype.php new file mode 100644 index 0000000..ba75a2c --- /dev/null +++ b/cacme/vendor/symfony/polyfill-ctype/Ctype.php @@ -0,0 +1,232 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Ctype; + +/** + * Ctype implementation through regex. + * + * @internal + * + * @author Gert de Pagter + */ +final class Ctype +{ + /** + * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. + * + * @see https://php.net/ctype-alnum + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_alnum($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is a letter, FALSE otherwise. + * + * @see https://php.net/ctype-alpha + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_alpha($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); + } + + /** + * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. + * + * @see https://php.net/ctype-cntrl + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_cntrl($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); + } + + /** + * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. + * + * @see https://php.net/ctype-digit + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_digit($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. + * + * @see https://php.net/ctype-graph + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_graph($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); + } + + /** + * Returns TRUE if every character in text is a lowercase letter. + * + * @see https://php.net/ctype-lower + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_lower($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); + } + + /** + * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. + * + * @see https://php.net/ctype-print + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_print($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); + } + + /** + * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. + * + * @see https://php.net/ctype-punct + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_punct($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); + } + + /** + * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. + * + * @see https://php.net/ctype-space + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_space($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); + } + + /** + * Returns TRUE if every character in text is an uppercase letter. + * + * @see https://php.net/ctype-upper + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_upper($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); + } + + /** + * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. + * + * @see https://php.net/ctype-xdigit + * + * @param mixed $text + * + * @return bool + */ + public static function ctype_xdigit($text) + { + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); + } + + /** + * Converts integers to their char versions according to normal ctype behaviour, if needed. + * + * If an integer between -128 and 255 inclusive is provided, + * it is interpreted as the ASCII value of a single character + * (negative values have 256 added in order to allow characters in the Extended ASCII range). + * Any other integer is interpreted as a string containing the decimal digits of the integer. + * + * @param mixed $int + * @param string $function + * + * @return mixed + */ + private static function convert_int_to_char_for_ctype($int, $function) + { + if (!\is_int($int)) { + return $int; + } + + if ($int < -128 || $int > 255) { + return (string) $int; + } + + if (\PHP_VERSION_ID >= 80100) { + @trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED); + } + + if ($int < 0) { + $int += 256; + } + + return \chr($int); + } +} diff --git a/cacme/vendor/symfony/polyfill-ctype/LICENSE b/cacme/vendor/symfony/polyfill-ctype/LICENSE new file mode 100644 index 0000000..7536cae --- /dev/null +++ b/cacme/vendor/symfony/polyfill-ctype/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-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/cacme/vendor/symfony/polyfill-ctype/README.md b/cacme/vendor/symfony/polyfill-ctype/README.md new file mode 100644 index 0000000..b144d03 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-ctype/README.md @@ -0,0 +1,12 @@ +Symfony Polyfill / Ctype +======================== + +This component provides `ctype_*` functions to users who run php versions without the ctype extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/cacme/vendor/symfony/polyfill-ctype/bootstrap.php b/cacme/vendor/symfony/polyfill-ctype/bootstrap.php new file mode 100644 index 0000000..d54524b --- /dev/null +++ b/cacme/vendor/symfony/polyfill-ctype/bootstrap.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!function_exists('ctype_alnum')) { + function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } +} +if (!function_exists('ctype_alpha')) { + function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } +} +if (!function_exists('ctype_cntrl')) { + function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } +} +if (!function_exists('ctype_digit')) { + function ctype_digit($text) { return p\Ctype::ctype_digit($text); } +} +if (!function_exists('ctype_graph')) { + function ctype_graph($text) { return p\Ctype::ctype_graph($text); } +} +if (!function_exists('ctype_lower')) { + function ctype_lower($text) { return p\Ctype::ctype_lower($text); } +} +if (!function_exists('ctype_print')) { + function ctype_print($text) { return p\Ctype::ctype_print($text); } +} +if (!function_exists('ctype_punct')) { + function ctype_punct($text) { return p\Ctype::ctype_punct($text); } +} +if (!function_exists('ctype_space')) { + function ctype_space($text) { return p\Ctype::ctype_space($text); } +} +if (!function_exists('ctype_upper')) { + function ctype_upper($text) { return p\Ctype::ctype_upper($text); } +} +if (!function_exists('ctype_xdigit')) { + function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } +} diff --git a/cacme/vendor/symfony/polyfill-ctype/bootstrap80.php b/cacme/vendor/symfony/polyfill-ctype/bootstrap80.php new file mode 100644 index 0000000..ab2f861 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-ctype/bootstrap80.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (!function_exists('ctype_alnum')) { + function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); } +} +if (!function_exists('ctype_alpha')) { + function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); } +} +if (!function_exists('ctype_cntrl')) { + function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); } +} +if (!function_exists('ctype_digit')) { + function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); } +} +if (!function_exists('ctype_graph')) { + function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); } +} +if (!function_exists('ctype_lower')) { + function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); } +} +if (!function_exists('ctype_print')) { + function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); } +} +if (!function_exists('ctype_punct')) { + function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); } +} +if (!function_exists('ctype_space')) { + function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); } +} +if (!function_exists('ctype_upper')) { + function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); } +} +if (!function_exists('ctype_xdigit')) { + function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); } +} diff --git a/cacme/vendor/symfony/polyfill-ctype/composer.json b/cacme/vendor/symfony/polyfill-ctype/composer.json new file mode 100644 index 0000000..e5c978f --- /dev/null +++ b/cacme/vendor/symfony/polyfill-ctype/composer.json @@ -0,0 +1,41 @@ +{ + "name": "symfony/polyfill-ctype", + "type": "library", + "description": "Symfony polyfill for ctype functions", + "keywords": ["polyfill", "compatibility", "portable", "ctype"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/cacme/vendor/symfony/polyfill-intl-grapheme/Grapheme.php b/cacme/vendor/symfony/polyfill-intl-grapheme/Grapheme.php new file mode 100644 index 0000000..5373f16 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-grapheme/Grapheme.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 Symfony\Polyfill\Intl\Grapheme; + +\define('SYMFONY_GRAPHEME_CLUSTER_RX', ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39) ? '\X' : Grapheme::GRAPHEME_CLUSTER_RX); + +/** + * Partial intl implementation in pure PHP. + * + * Implemented: + * - grapheme_extract - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8 + * - grapheme_stripos - Find position (in grapheme units) of first occurrence of a case-insensitive string + * - grapheme_stristr - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack + * - grapheme_strlen - Get string length in grapheme units + * - grapheme_strpos - Find position (in grapheme units) of first occurrence of a string + * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string + * - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string + * - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack + * - grapheme_substr - Return part of a string + * + * @author Nicolas Grekas + * + * @internal + */ +final class Grapheme +{ + // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control]) + // This regular expression is a work around for http://bugs.exim.org/1279 + public const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])'; + + private const CASE_FOLD = [ + ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], + ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], + ]; + + public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0) + { + if (0 > $start) { + $start = \strlen($s) + $start; + } + + if (!\is_scalar($s)) { + $hasError = false; + set_error_handler(function () use (&$hasError) { $hasError = true; }); + $next = substr($s, $start); + restore_error_handler(); + if ($hasError) { + substr($s, $start); + $s = ''; + } else { + $s = $next; + } + } else { + $s = substr($s, $start); + } + $size = (int) $size; + $type = (int) $type; + $start = (int) $start; + + if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) { + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS'); + } + + if (!isset($s[0]) || 0 > $size || 0 > $start) { + return false; + } + if (0 === $size) { + return ''; + } + + $next = $start; + + $s = preg_split('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', "\r\n".$s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); + + if (!isset($s[1])) { + return false; + } + + $i = 1; + $ret = ''; + + do { + if (\GRAPHEME_EXTR_COUNT === $type) { + --$size; + } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) { + $size -= \strlen($s[$i]); + } else { + $size -= iconv_strlen($s[$i], 'UTF-8//IGNORE'); + } + + if ($size >= 0) { + $ret .= $s[$i]; + } + } while (isset($s[++$i]) && $size > 0); + + $next += \strlen($ret); + + return $ret; + } + + public static function grapheme_strlen($s) + { + preg_replace('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', '', $s, -1, $len); + + return 0 === $len && '' !== $s ? null : $len; + } + + public static function grapheme_substr($s, $start, $len = null) + { + if (null === $len) { + $len = 2147483647; + } + + preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s, $s); + + $slen = \count($s[0]); + $start = (int) $start; + + if (0 > $start) { + $start += $slen; + } + if (0 > $start) { + if (\PHP_VERSION_ID < 80000) { + return false; + } + + $start = 0; + } + if ($start >= $slen) { + return \PHP_VERSION_ID >= 80000 ? '' : false; + } + + $rem = $slen - $start; + + if (0 > $len) { + $len += $rem; + } + if (0 === $len) { + return ''; + } + if (0 > $len) { + return \PHP_VERSION_ID >= 80000 ? '' : false; + } + if ($len > $rem) { + $len = $rem; + } + + return implode('', \array_slice($s[0], $start, $len)); + } + + public static function grapheme_strpos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 0); + } + + public static function grapheme_stripos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 1); + } + + public static function grapheme_strrpos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 2); + } + + public static function grapheme_strripos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 3); + } + + public static function grapheme_stristr($s, $needle, $beforeNeedle = false) + { + return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8'); + } + + public static function grapheme_strstr($s, $needle, $beforeNeedle = false) + { + return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8'); + } + + private static function grapheme_position($s, $needle, $offset, $mode) + { + $needle = (string) $needle; + if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) { + return false; + } + $s = (string) $s; + if (!preg_match('/./us', $s)) { + return false; + } + if ($offset > 0) { + $s = self::grapheme_substr($s, $offset); + } elseif ($offset < 0) { + if (2 > $mode) { + $offset += self::grapheme_strlen($s); + $s = self::grapheme_substr($s, $offset); + if (0 > $offset) { + $offset = 0; + } + } elseif (0 > $offset += self::grapheme_strlen($needle)) { + $s = self::grapheme_substr($s, 0, $offset); + $offset = 0; + } else { + $offset = 0; + } + } + + // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8, + // we can use normal binary string functions here. For case-insensitive searches, + // case fold the strings first. + $caseInsensitive = $mode & 1; + $reverse = $mode & 2; + if ($caseInsensitive) { + // Use the same case folding mode as mbstring does for mb_stripos(). + // Stick to SIMPLE case folding to avoid changing the length of the string, which + // might result in offsets being shifted. + $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER; + $s = mb_convert_case($s, $mode, 'UTF-8'); + $needle = mb_convert_case($needle, $mode, 'UTF-8'); + + if (!\defined('MB_CASE_FOLD_SIMPLE')) { + $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); + $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle); + } + } + if ($reverse) { + $needlePos = strrpos($s, $needle); + } else { + $needlePos = strpos($s, $needle); + } + + return false !== $needlePos ? self::grapheme_strlen(substr($s, 0, $needlePos)) + $offset : false; + } +} diff --git a/cacme/vendor/symfony/polyfill-intl-grapheme/LICENSE b/cacme/vendor/symfony/polyfill-intl-grapheme/LICENSE new file mode 100644 index 0000000..6e3afce --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-grapheme/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-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/cacme/vendor/symfony/polyfill-intl-grapheme/README.md b/cacme/vendor/symfony/polyfill-intl-grapheme/README.md new file mode 100644 index 0000000..f55d92c --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-grapheme/README.md @@ -0,0 +1,31 @@ +Symfony Polyfill / Intl: Grapheme +================================= + +This component provides a partial, native PHP implementation of the +[Grapheme functions](https://php.net/intl.grapheme) from the +[Intl](https://php.net/intl) extension. + +- [`grapheme_extract`](https://php.net/grapheme_extract): Extract a sequence of grapheme + clusters from a text buffer, which must be encoded in UTF-8 +- [`grapheme_stripos`](https://php.net/grapheme_stripos): Find position (in grapheme units) + of first occurrence of a case-insensitive string +- [`grapheme_stristr`](https://php.net/grapheme_stristr): Returns part of haystack string + from the first occurrence of case-insensitive needle to the end of haystack +- [`grapheme_strlen`](https://php.net/grapheme_strlen): Get string length in grapheme units +- [`grapheme_strpos`](https://php.net/grapheme_strpos): Find position (in grapheme units) + of first occurrence of a string +- [`grapheme_strripos`](https://php.net/grapheme_strripos): Find position (in grapheme units) + of last occurrence of a case-insensitive string +- [`grapheme_strrpos`](https://php.net/grapheme_strrpos): Find position (in grapheme units) + of last occurrence of a string +- [`grapheme_strstr`](https://php.net/grapheme_strstr): Returns part of haystack string from + the first occurrence of needle to the end of haystack +- [`grapheme_substr`](https://php.net/grapheme_substr): Return part of a string + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap.php b/cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap.php new file mode 100644 index 0000000..a9ea03c --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Grapheme as p; + +if (extension_loaded('intl')) { + return; +} + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!defined('GRAPHEME_EXTR_COUNT')) { + define('GRAPHEME_EXTR_COUNT', 0); +} +if (!defined('GRAPHEME_EXTR_MAXBYTES')) { + define('GRAPHEME_EXTR_MAXBYTES', 1); +} +if (!defined('GRAPHEME_EXTR_MAXCHARS')) { + define('GRAPHEME_EXTR_MAXCHARS', 2); +} + +if (!function_exists('grapheme_extract')) { + function grapheme_extract($haystack, $size, $type = 0, $start = 0, &$next = 0) { return p\Grapheme::grapheme_extract($haystack, $size, $type, $start, $next); } +} +if (!function_exists('grapheme_stripos')) { + function grapheme_stripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_stripos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_stristr')) { + function grapheme_stristr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_stristr($haystack, $needle, $beforeNeedle); } +} +if (!function_exists('grapheme_strlen')) { + function grapheme_strlen($input) { return p\Grapheme::grapheme_strlen($input); } +} +if (!function_exists('grapheme_strpos')) { + function grapheme_strpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strpos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_strripos')) { + function grapheme_strripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strripos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_strrpos')) { + function grapheme_strrpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strrpos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_strstr')) { + function grapheme_strstr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_strstr($haystack, $needle, $beforeNeedle); } +} +if (!function_exists('grapheme_substr')) { + function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); } +} diff --git a/cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php b/cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php new file mode 100644 index 0000000..b8c0786 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Grapheme as p; + +if (!defined('GRAPHEME_EXTR_COUNT')) { + define('GRAPHEME_EXTR_COUNT', 0); +} +if (!defined('GRAPHEME_EXTR_MAXBYTES')) { + define('GRAPHEME_EXTR_MAXBYTES', 1); +} +if (!defined('GRAPHEME_EXTR_MAXCHARS')) { + define('GRAPHEME_EXTR_MAXCHARS', 2); +} + +if (!function_exists('grapheme_extract')) { + function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null): string|false { return p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next); } +} +if (!function_exists('grapheme_stripos')) { + function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_stristr')) { + function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle); } +} +if (!function_exists('grapheme_strlen')) { + function grapheme_strlen(?string $string): int|false|null { return p\Grapheme::grapheme_strlen((string) $string); } +} +if (!function_exists('grapheme_strpos')) { + function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_strripos')) { + function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_strrpos')) { + function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_strstr')) { + function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle); } +} +if (!function_exists('grapheme_substr')) { + function grapheme_substr(?string $string, ?int $offset, ?int $length = null): string|false { return p\Grapheme::grapheme_substr((string) $string, (int) $offset, $length); } +} diff --git a/cacme/vendor/symfony/polyfill-intl-grapheme/composer.json b/cacme/vendor/symfony/polyfill-intl-grapheme/composer.json new file mode 100644 index 0000000..a20d3fa --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-grapheme/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/polyfill-intl-grapheme", + "type": "library", + "description": "Symfony polyfill for intl's grapheme_* functions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "grapheme"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-intl": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/LICENSE b/cacme/vendor/symfony/polyfill-intl-normalizer/LICENSE new file mode 100644 index 0000000..6e3afce --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-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/cacme/vendor/symfony/polyfill-intl-normalizer/Normalizer.php b/cacme/vendor/symfony/polyfill-intl-normalizer/Normalizer.php new file mode 100644 index 0000000..81704ab --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/Normalizer.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 Symfony\Polyfill\Intl\Normalizer; + +/** + * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension. + * + * It has been validated with Unicode 6.3 Normalization Conformance Test. + * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations. + * + * @author Nicolas Grekas + * + * @internal + */ +class Normalizer +{ + public const FORM_D = \Normalizer::FORM_D; + public const FORM_KD = \Normalizer::FORM_KD; + public const FORM_C = \Normalizer::FORM_C; + public const FORM_KC = \Normalizer::FORM_KC; + public const NFD = \Normalizer::NFD; + public const NFKD = \Normalizer::NFKD; + public const NFC = \Normalizer::NFC; + public const NFKC = \Normalizer::NFKC; + + private static $C; + private static $D; + private static $KD; + private static $cC; + private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; + private static $ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; + + public static function isNormalized(string $s, int $form = self::FORM_C) + { + if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) { + return false; + } + if (!isset($s[strspn($s, self::$ASCII)])) { + return true; + } + if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) { + return true; + } + + return self::normalize($s, $form) === $s; + } + + public static function normalize(string $s, int $form = self::FORM_C) + { + if (!preg_match('//u', $s)) { + return false; + } + + switch ($form) { + case self::NFC: $C = true; $K = false; break; + case self::NFD: $C = false; $K = false; break; + case self::NFKC: $C = true; $K = true; break; + case self::NFKD: $C = false; $K = true; break; + default: + if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) { + return $s; + } + + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form'); + } + + if ('' === $s) { + return ''; + } + + if ($K && null === self::$KD) { + self::$KD = self::getData('compatibilityDecomposition'); + } + + if (null === self::$D) { + self::$D = self::getData('canonicalDecomposition'); + self::$cC = self::getData('combiningClass'); + } + + if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) { + mb_internal_encoding('8bit'); + } + + $r = self::decompose($s, $K); + + if ($C) { + if (null === self::$C) { + self::$C = self::getData('canonicalComposition'); + } + + $r = self::recompose($r); + } + if (null !== $mbEncoding) { + mb_internal_encoding($mbEncoding); + } + + return $r; + } + + private static function recompose($s) + { + $ASCII = self::$ASCII; + $compMap = self::$C; + $combClass = self::$cC; + $ulenMask = self::$ulenMask; + + $result = $tail = ''; + + $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"]; + $len = \strlen($s); + + $lastUchr = substr($s, 0, $i); + $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0; + + while ($i < $len) { + if ($s[$i] < "\x80") { + // ASCII chars + + if ($tail) { + $lastUchr .= $tail; + $tail = ''; + } + + if ($j = strspn($s, $ASCII, $i + 1)) { + $lastUchr .= substr($s, $i, $j); + $i += $j; + } + + $result .= $lastUchr; + $lastUchr = $s[$i]; + $lastUcls = 0; + ++$i; + continue; + } + + $ulen = $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + + if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr + || $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr + || $lastUcls) { + // Table lookup and combining chars composition + + $ucls = $combClass[$uchr] ?? 0; + + if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) { + $lastUchr = $compMap[$lastUchr.$uchr]; + } elseif ($lastUcls = $ucls) { + $tail .= $uchr; + } else { + if ($tail) { + $lastUchr .= $tail; + $tail = ''; + } + + $result .= $lastUchr; + $lastUchr = $uchr; + } + } else { + // Hangul chars + + $L = \ord($lastUchr[2]) - 0x80; + $V = \ord($uchr[2]) - 0xA1; + $T = 0; + + $uchr = substr($s, $i + $ulen, 3); + + if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") { + $T = \ord($uchr[2]) - 0xA7; + 0 > $T && $T += 0x40; + $ulen += 3; + } + + $L = 0xAC00 + ($L * 21 + $V) * 28 + $T; + $lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F); + } + + $i += $ulen; + } + + return $result.$lastUchr.$tail; + } + + private static function decompose($s, $c) + { + $result = ''; + + $ASCII = self::$ASCII; + $decompMap = self::$D; + $combClass = self::$cC; + $ulenMask = self::$ulenMask; + if ($c) { + $compatMap = self::$KD; + } + + $c = []; + $i = 0; + $len = \strlen($s); + + while ($i < $len) { + if ($s[$i] < "\x80") { + // ASCII chars + + if ($c) { + ksort($c); + $result .= implode('', $c); + $c = []; + } + + $j = 1 + strspn($s, $ASCII, $i + 1); + $result .= substr($s, $i, $j); + $i += $j; + continue; + } + + $ulen = $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + + if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) { + // Table lookup + + if ($uchr !== $j = $compatMap[$uchr] ?? ($decompMap[$uchr] ?? $uchr)) { + $uchr = $j; + + $j = \strlen($uchr); + $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"]; + + if ($ulen != $j) { + // Put trailing chars in $s + + $j -= $ulen; + $i -= $j; + + if (0 > $i) { + $s = str_repeat(' ', -$i).$s; + $len -= $i; + $i = 0; + } + + while ($j--) { + $s[$i + $j] = $uchr[$ulen + $j]; + } + + $uchr = substr($uchr, 0, $ulen); + } + } + if (isset($combClass[$uchr])) { + // Combining chars, for sorting + + if (!isset($c[$combClass[$uchr]])) { + $c[$combClass[$uchr]] = ''; + } + $c[$combClass[$uchr]] .= $uchr; + continue; + } + } else { + // Hangul chars + + $uchr = unpack('C*', $uchr); + $j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80; + + $uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588)) + ."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28)); + + if ($j %= 28) { + $uchr .= $j < 25 + ? ("\xE1\x86".\chr(0xA7 + $j)) + : ("\xE1\x87".\chr(0x67 + $j)); + } + } + if ($c) { + ksort($c); + $result .= implode('', $c); + $c = []; + } + + $result .= $uchr; + } + + if ($c) { + ksort($c); + $result .= implode('', $c); + } + + return $result; + } + + private static function getData($file) + { + if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { + return require $file; + } + + return false; + } +} diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/README.md b/cacme/vendor/symfony/polyfill-intl-normalizer/README.md new file mode 100644 index 0000000..b9b762e --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/README.md @@ -0,0 +1,14 @@ +Symfony Polyfill / Intl: Normalizer +=================================== + +This component provides a fallback implementation for the +[`Normalizer`](https://php.net/Normalizer) class provided +by the [Intl](https://php.net/intl) extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php new file mode 100644 index 0000000..0fdfc89 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php @@ -0,0 +1,17 @@ + 'À', + 'Á' => 'Á', + 'Â' => 'Â', + 'Ã' => 'Ã', + 'Ä' => 'Ä', + 'Å' => 'Å', + 'Ç' => 'Ç', + 'È' => 'È', + 'É' => 'É', + 'Ê' => 'Ê', + 'Ë' => 'Ë', + 'Ì' => 'Ì', + 'Í' => 'Í', + 'Î' => 'Î', + 'Ï' => 'Ï', + 'Ñ' => 'Ñ', + 'Ò' => 'Ò', + 'Ó' => 'Ó', + 'Ô' => 'Ô', + 'Õ' => 'Õ', + 'Ö' => 'Ö', + 'Ù' => 'Ù', + 'Ú' => 'Ú', + 'Û' => 'Û', + 'Ü' => 'Ü', + 'Ý' => 'Ý', + 'à' => 'à', + 'á' => 'á', + 'â' => 'â', + 'ã' => 'ã', + 'ä' => 'ä', + 'å' => 'å', + 'ç' => 'ç', + 'è' => 'è', + 'é' => 'é', + 'ê' => 'ê', + 'ë' => 'ë', + 'ì' => 'ì', + 'í' => 'í', + 'î' => 'î', + 'ï' => 'ï', + 'ñ' => 'ñ', + 'ò' => 'ò', + 'ó' => 'ó', + 'ô' => 'ô', + 'õ' => 'õ', + 'ö' => 'ö', + 'ù' => 'ù', + 'ú' => 'ú', + 'û' => 'û', + 'ü' => 'ü', + 'ý' => 'ý', + 'ÿ' => 'ÿ', + 'Ā' => 'Ā', + 'ā' => 'ā', + 'Ă' => 'Ă', + 'ă' => 'ă', + 'Ą' => 'Ą', + 'ą' => 'ą', + 'Ć' => 'Ć', + 'ć' => 'ć', + 'Ĉ' => 'Ĉ', + 'ĉ' => 'ĉ', + 'Ċ' => 'Ċ', + 'ċ' => 'ċ', + 'Č' => 'Č', + 'č' => 'č', + 'Ď' => 'Ď', + 'ď' => 'ď', + 'Ē' => 'Ē', + 'ē' => 'ē', + 'Ĕ' => 'Ĕ', + 'ĕ' => 'ĕ', + 'Ė' => 'Ė', + 'ė' => 'ė', + 'Ę' => 'Ę', + 'ę' => 'ę', + 'Ě' => 'Ě', + 'ě' => 'ě', + 'Ĝ' => 'Ĝ', + 'ĝ' => 'ĝ', + 'Ğ' => 'Ğ', + 'ğ' => 'ğ', + 'Ġ' => 'Ġ', + 'ġ' => 'ġ', + 'Ģ' => 'Ģ', + 'ģ' => 'ģ', + 'Ĥ' => 'Ĥ', + 'ĥ' => 'ĥ', + 'Ĩ' => 'Ĩ', + 'ĩ' => 'ĩ', + 'Ī' => 'Ī', + 'ī' => 'ī', + 'Ĭ' => 'Ĭ', + 'ĭ' => 'ĭ', + 'Į' => 'Į', + 'į' => 'į', + 'İ' => 'İ', + 'Ĵ' => 'Ĵ', + 'ĵ' => 'ĵ', + 'Ķ' => 'Ķ', + 'ķ' => 'ķ', + 'Ĺ' => 'Ĺ', + 'ĺ' => 'ĺ', + 'Ļ' => 'Ļ', + 'ļ' => 'ļ', + 'Ľ' => 'Ľ', + 'ľ' => 'ľ', + 'Ń' => 'Ń', + 'ń' => 'ń', + 'Ņ' => 'Ņ', + 'ņ' => 'ņ', + 'Ň' => 'Ň', + 'ň' => 'ň', + 'Ō' => 'Ō', + 'ō' => 'ō', + 'Ŏ' => 'Ŏ', + 'ŏ' => 'ŏ', + 'Ő' => 'Ő', + 'ő' => 'ő', + 'Ŕ' => 'Ŕ', + 'ŕ' => 'ŕ', + 'Ŗ' => 'Ŗ', + 'ŗ' => 'ŗ', + 'Ř' => 'Ř', + 'ř' => 'ř', + 'Ś' => 'Ś', + 'ś' => 'ś', + 'Ŝ' => 'Ŝ', + 'ŝ' => 'ŝ', + 'Ş' => 'Ş', + 'ş' => 'ş', + 'Š' => 'Š', + 'š' => 'š', + 'Ţ' => 'Ţ', + 'ţ' => 'ţ', + 'Ť' => 'Ť', + 'ť' => 'ť', + 'Ũ' => 'Ũ', + 'ũ' => 'ũ', + 'Ū' => 'Ū', + 'ū' => 'ū', + 'Ŭ' => 'Ŭ', + 'ŭ' => 'ŭ', + 'Ů' => 'Ů', + 'ů' => 'ů', + 'Ű' => 'Ű', + 'ű' => 'ű', + 'Ų' => 'Ų', + 'ų' => 'ų', + 'Ŵ' => 'Ŵ', + 'ŵ' => 'ŵ', + 'Ŷ' => 'Ŷ', + 'ŷ' => 'ŷ', + 'Ÿ' => 'Ÿ', + 'Ź' => 'Ź', + 'ź' => 'ź', + 'Ż' => 'Ż', + 'ż' => 'ż', + 'Ž' => 'Ž', + 'ž' => 'ž', + 'Ơ' => 'Ơ', + 'ơ' => 'ơ', + 'Ư' => 'Ư', + 'ư' => 'ư', + 'Ǎ' => 'Ǎ', + 'ǎ' => 'ǎ', + 'Ǐ' => 'Ǐ', + 'ǐ' => 'ǐ', + 'Ǒ' => 'Ǒ', + 'ǒ' => 'ǒ', + 'Ǔ' => 'Ǔ', + 'ǔ' => 'ǔ', + 'Ǖ' => 'Ǖ', + 'ǖ' => 'ǖ', + 'Ǘ' => 'Ǘ', + 'ǘ' => 'ǘ', + 'Ǚ' => 'Ǚ', + 'ǚ' => 'ǚ', + 'Ǜ' => 'Ǜ', + 'ǜ' => 'ǜ', + 'Ǟ' => 'Ǟ', + 'ǟ' => 'ǟ', + 'Ǡ' => 'Ǡ', + 'ǡ' => 'ǡ', + 'Ǣ' => 'Ǣ', + 'ǣ' => 'ǣ', + 'Ǧ' => 'Ǧ', + 'ǧ' => 'ǧ', + 'Ǩ' => 'Ǩ', + 'ǩ' => 'ǩ', + 'Ǫ' => 'Ǫ', + 'ǫ' => 'ǫ', + 'Ǭ' => 'Ǭ', + 'ǭ' => 'ǭ', + 'Ǯ' => 'Ǯ', + 'ǯ' => 'ǯ', + 'ǰ' => 'ǰ', + 'Ǵ' => 'Ǵ', + 'ǵ' => 'ǵ', + 'Ǹ' => 'Ǹ', + 'ǹ' => 'ǹ', + 'Ǻ' => 'Ǻ', + 'ǻ' => 'ǻ', + 'Ǽ' => 'Ǽ', + 'ǽ' => 'ǽ', + 'Ǿ' => 'Ǿ', + 'ǿ' => 'ǿ', + 'Ȁ' => 'Ȁ', + 'ȁ' => 'ȁ', + 'Ȃ' => 'Ȃ', + 'ȃ' => 'ȃ', + 'Ȅ' => 'Ȅ', + 'ȅ' => 'ȅ', + 'Ȇ' => 'Ȇ', + 'ȇ' => 'ȇ', + 'Ȉ' => 'Ȉ', + 'ȉ' => 'ȉ', + 'Ȋ' => 'Ȋ', + 'ȋ' => 'ȋ', + 'Ȍ' => 'Ȍ', + 'ȍ' => 'ȍ', + 'Ȏ' => 'Ȏ', + 'ȏ' => 'ȏ', + 'Ȑ' => 'Ȑ', + 'ȑ' => 'ȑ', + 'Ȓ' => 'Ȓ', + 'ȓ' => 'ȓ', + 'Ȕ' => 'Ȕ', + 'ȕ' => 'ȕ', + 'Ȗ' => 'Ȗ', + 'ȗ' => 'ȗ', + 'Ș' => 'Ș', + 'ș' => 'ș', + 'Ț' => 'Ț', + 'ț' => 'ț', + 'Ȟ' => 'Ȟ', + 'ȟ' => 'ȟ', + 'Ȧ' => 'Ȧ', + 'ȧ' => 'ȧ', + 'Ȩ' => 'Ȩ', + 'ȩ' => 'ȩ', + 'Ȫ' => 'Ȫ', + 'ȫ' => 'ȫ', + 'Ȭ' => 'Ȭ', + 'ȭ' => 'ȭ', + 'Ȯ' => 'Ȯ', + 'ȯ' => 'ȯ', + 'Ȱ' => 'Ȱ', + 'ȱ' => 'ȱ', + 'Ȳ' => 'Ȳ', + 'ȳ' => 'ȳ', + '΅' => '΅', + 'Ά' => 'Ά', + 'Έ' => 'Έ', + 'Ή' => 'Ή', + 'Ί' => 'Ί', + 'Ό' => 'Ό', + 'Ύ' => 'Ύ', + 'Ώ' => 'Ώ', + 'ΐ' => 'ΐ', + 'Ϊ' => 'Ϊ', + 'Ϋ' => 'Ϋ', + 'ά' => 'ά', + 'έ' => 'έ', + 'ή' => 'ή', + 'ί' => 'ί', + 'ΰ' => 'ΰ', + 'ϊ' => 'ϊ', + 'ϋ' => 'ϋ', + 'ό' => 'ό', + 'ύ' => 'ύ', + 'ώ' => 'ώ', + 'ϓ' => 'ϓ', + 'ϔ' => 'ϔ', + 'Ѐ' => 'Ѐ', + 'Ё' => 'Ё', + 'Ѓ' => 'Ѓ', + 'Ї' => 'Ї', + 'Ќ' => 'Ќ', + 'Ѝ' => 'Ѝ', + 'Ў' => 'Ў', + 'Й' => 'Й', + 'й' => 'й', + 'ѐ' => 'ѐ', + 'ё' => 'ё', + 'ѓ' => 'ѓ', + 'ї' => 'ї', + 'ќ' => 'ќ', + 'ѝ' => 'ѝ', + 'ў' => 'ў', + 'Ѷ' => 'Ѷ', + 'ѷ' => 'ѷ', + 'Ӂ' => 'Ӂ', + 'ӂ' => 'ӂ', + 'Ӑ' => 'Ӑ', + 'ӑ' => 'ӑ', + 'Ӓ' => 'Ӓ', + 'ӓ' => 'ӓ', + 'Ӗ' => 'Ӗ', + 'ӗ' => 'ӗ', + 'Ӛ' => 'Ӛ', + 'ӛ' => 'ӛ', + 'Ӝ' => 'Ӝ', + 'ӝ' => 'ӝ', + 'Ӟ' => 'Ӟ', + 'ӟ' => 'ӟ', + 'Ӣ' => 'Ӣ', + 'ӣ' => 'ӣ', + 'Ӥ' => 'Ӥ', + 'ӥ' => 'ӥ', + 'Ӧ' => 'Ӧ', + 'ӧ' => 'ӧ', + 'Ӫ' => 'Ӫ', + 'ӫ' => 'ӫ', + 'Ӭ' => 'Ӭ', + 'ӭ' => 'ӭ', + 'Ӯ' => 'Ӯ', + 'ӯ' => 'ӯ', + 'Ӱ' => 'Ӱ', + 'ӱ' => 'ӱ', + 'Ӳ' => 'Ӳ', + 'ӳ' => 'ӳ', + 'Ӵ' => 'Ӵ', + 'ӵ' => 'ӵ', + 'Ӹ' => 'Ӹ', + 'ӹ' => 'ӹ', + 'آ' => 'آ', + 'أ' => 'أ', + 'ؤ' => 'ؤ', + 'إ' => 'إ', + 'ئ' => 'ئ', + 'ۀ' => 'ۀ', + 'ۂ' => 'ۂ', + 'ۓ' => 'ۓ', + 'ऩ' => 'ऩ', + 'ऱ' => 'ऱ', + 'ऴ' => 'ऴ', + 'ো' => 'ো', + 'ৌ' => 'ৌ', + 'ୈ' => 'ୈ', + 'ୋ' => 'ୋ', + 'ୌ' => 'ୌ', + 'ஔ' => 'ஔ', + 'ொ' => 'ொ', + 'ோ' => 'ோ', + 'ௌ' => 'ௌ', + 'ై' => 'ై', + 'ೀ' => 'ೀ', + 'ೇ' => 'ೇ', + 'ೈ' => 'ೈ', + 'ೊ' => 'ೊ', + 'ೋ' => 'ೋ', + 'ൊ' => 'ൊ', + 'ോ' => 'ോ', + 'ൌ' => 'ൌ', + 'ේ' => 'ේ', + 'ො' => 'ො', + 'ෝ' => 'ෝ', + 'ෞ' => 'ෞ', + 'ဦ' => 'ဦ', + 'ᬆ' => 'ᬆ', + 'ᬈ' => 'ᬈ', + 'ᬊ' => 'ᬊ', + 'ᬌ' => 'ᬌ', + 'ᬎ' => 'ᬎ', + 'ᬒ' => 'ᬒ', + 'ᬻ' => 'ᬻ', + 'ᬽ' => 'ᬽ', + 'ᭀ' => 'ᭀ', + 'ᭁ' => 'ᭁ', + 'ᭃ' => 'ᭃ', + 'Ḁ' => 'Ḁ', + 'ḁ' => 'ḁ', + 'Ḃ' => 'Ḃ', + 'ḃ' => 'ḃ', + 'Ḅ' => 'Ḅ', + 'ḅ' => 'ḅ', + 'Ḇ' => 'Ḇ', + 'ḇ' => 'ḇ', + 'Ḉ' => 'Ḉ', + 'ḉ' => 'ḉ', + 'Ḋ' => 'Ḋ', + 'ḋ' => 'ḋ', + 'Ḍ' => 'Ḍ', + 'ḍ' => 'ḍ', + 'Ḏ' => 'Ḏ', + 'ḏ' => 'ḏ', + 'Ḑ' => 'Ḑ', + 'ḑ' => 'ḑ', + 'Ḓ' => 'Ḓ', + 'ḓ' => 'ḓ', + 'Ḕ' => 'Ḕ', + 'ḕ' => 'ḕ', + 'Ḗ' => 'Ḗ', + 'ḗ' => 'ḗ', + 'Ḙ' => 'Ḙ', + 'ḙ' => 'ḙ', + 'Ḛ' => 'Ḛ', + 'ḛ' => 'ḛ', + 'Ḝ' => 'Ḝ', + 'ḝ' => 'ḝ', + 'Ḟ' => 'Ḟ', + 'ḟ' => 'ḟ', + 'Ḡ' => 'Ḡ', + 'ḡ' => 'ḡ', + 'Ḣ' => 'Ḣ', + 'ḣ' => 'ḣ', + 'Ḥ' => 'Ḥ', + 'ḥ' => 'ḥ', + 'Ḧ' => 'Ḧ', + 'ḧ' => 'ḧ', + 'Ḩ' => 'Ḩ', + 'ḩ' => 'ḩ', + 'Ḫ' => 'Ḫ', + 'ḫ' => 'ḫ', + 'Ḭ' => 'Ḭ', + 'ḭ' => 'ḭ', + 'Ḯ' => 'Ḯ', + 'ḯ' => 'ḯ', + 'Ḱ' => 'Ḱ', + 'ḱ' => 'ḱ', + 'Ḳ' => 'Ḳ', + 'ḳ' => 'ḳ', + 'Ḵ' => 'Ḵ', + 'ḵ' => 'ḵ', + 'Ḷ' => 'Ḷ', + 'ḷ' => 'ḷ', + 'Ḹ' => 'Ḹ', + 'ḹ' => 'ḹ', + 'Ḻ' => 'Ḻ', + 'ḻ' => 'ḻ', + 'Ḽ' => 'Ḽ', + 'ḽ' => 'ḽ', + 'Ḿ' => 'Ḿ', + 'ḿ' => 'ḿ', + 'Ṁ' => 'Ṁ', + 'ṁ' => 'ṁ', + 'Ṃ' => 'Ṃ', + 'ṃ' => 'ṃ', + 'Ṅ' => 'Ṅ', + 'ṅ' => 'ṅ', + 'Ṇ' => 'Ṇ', + 'ṇ' => 'ṇ', + 'Ṉ' => 'Ṉ', + 'ṉ' => 'ṉ', + 'Ṋ' => 'Ṋ', + 'ṋ' => 'ṋ', + 'Ṍ' => 'Ṍ', + 'ṍ' => 'ṍ', + 'Ṏ' => 'Ṏ', + 'ṏ' => 'ṏ', + 'Ṑ' => 'Ṑ', + 'ṑ' => 'ṑ', + 'Ṓ' => 'Ṓ', + 'ṓ' => 'ṓ', + 'Ṕ' => 'Ṕ', + 'ṕ' => 'ṕ', + 'Ṗ' => 'Ṗ', + 'ṗ' => 'ṗ', + 'Ṙ' => 'Ṙ', + 'ṙ' => 'ṙ', + 'Ṛ' => 'Ṛ', + 'ṛ' => 'ṛ', + 'Ṝ' => 'Ṝ', + 'ṝ' => 'ṝ', + 'Ṟ' => 'Ṟ', + 'ṟ' => 'ṟ', + 'Ṡ' => 'Ṡ', + 'ṡ' => 'ṡ', + 'Ṣ' => 'Ṣ', + 'ṣ' => 'ṣ', + 'Ṥ' => 'Ṥ', + 'ṥ' => 'ṥ', + 'Ṧ' => 'Ṧ', + 'ṧ' => 'ṧ', + 'Ṩ' => 'Ṩ', + 'ṩ' => 'ṩ', + 'Ṫ' => 'Ṫ', + 'ṫ' => 'ṫ', + 'Ṭ' => 'Ṭ', + 'ṭ' => 'ṭ', + 'Ṯ' => 'Ṯ', + 'ṯ' => 'ṯ', + 'Ṱ' => 'Ṱ', + 'ṱ' => 'ṱ', + 'Ṳ' => 'Ṳ', + 'ṳ' => 'ṳ', + 'Ṵ' => 'Ṵ', + 'ṵ' => 'ṵ', + 'Ṷ' => 'Ṷ', + 'ṷ' => 'ṷ', + 'Ṹ' => 'Ṹ', + 'ṹ' => 'ṹ', + 'Ṻ' => 'Ṻ', + 'ṻ' => 'ṻ', + 'Ṽ' => 'Ṽ', + 'ṽ' => 'ṽ', + 'Ṿ' => 'Ṿ', + 'ṿ' => 'ṿ', + 'Ẁ' => 'Ẁ', + 'ẁ' => 'ẁ', + 'Ẃ' => 'Ẃ', + 'ẃ' => 'ẃ', + 'Ẅ' => 'Ẅ', + 'ẅ' => 'ẅ', + 'Ẇ' => 'Ẇ', + 'ẇ' => 'ẇ', + 'Ẉ' => 'Ẉ', + 'ẉ' => 'ẉ', + 'Ẋ' => 'Ẋ', + 'ẋ' => 'ẋ', + 'Ẍ' => 'Ẍ', + 'ẍ' => 'ẍ', + 'Ẏ' => 'Ẏ', + 'ẏ' => 'ẏ', + 'Ẑ' => 'Ẑ', + 'ẑ' => 'ẑ', + 'Ẓ' => 'Ẓ', + 'ẓ' => 'ẓ', + 'Ẕ' => 'Ẕ', + 'ẕ' => 'ẕ', + 'ẖ' => 'ẖ', + 'ẗ' => 'ẗ', + 'ẘ' => 'ẘ', + 'ẙ' => 'ẙ', + 'ẛ' => 'ẛ', + 'Ạ' => 'Ạ', + 'ạ' => 'ạ', + 'Ả' => 'Ả', + 'ả' => 'ả', + 'Ấ' => 'Ấ', + 'ấ' => 'ấ', + 'Ầ' => 'Ầ', + 'ầ' => 'ầ', + 'Ẩ' => 'Ẩ', + 'ẩ' => 'ẩ', + 'Ẫ' => 'Ẫ', + 'ẫ' => 'ẫ', + 'Ậ' => 'Ậ', + 'ậ' => 'ậ', + 'Ắ' => 'Ắ', + 'ắ' => 'ắ', + 'Ằ' => 'Ằ', + 'ằ' => 'ằ', + 'Ẳ' => 'Ẳ', + 'ẳ' => 'ẳ', + 'Ẵ' => 'Ẵ', + 'ẵ' => 'ẵ', + 'Ặ' => 'Ặ', + 'ặ' => 'ặ', + 'Ẹ' => 'Ẹ', + 'ẹ' => 'ẹ', + 'Ẻ' => 'Ẻ', + 'ẻ' => 'ẻ', + 'Ẽ' => 'Ẽ', + 'ẽ' => 'ẽ', + 'Ế' => 'Ế', + 'ế' => 'ế', + 'Ề' => 'Ề', + 'ề' => 'ề', + 'Ể' => 'Ể', + 'ể' => 'ể', + 'Ễ' => 'Ễ', + 'ễ' => 'ễ', + 'Ệ' => 'Ệ', + 'ệ' => 'ệ', + 'Ỉ' => 'Ỉ', + 'ỉ' => 'ỉ', + 'Ị' => 'Ị', + 'ị' => 'ị', + 'Ọ' => 'Ọ', + 'ọ' => 'ọ', + 'Ỏ' => 'Ỏ', + 'ỏ' => 'ỏ', + 'Ố' => 'Ố', + 'ố' => 'ố', + 'Ồ' => 'Ồ', + 'ồ' => 'ồ', + 'Ổ' => 'Ổ', + 'ổ' => 'ổ', + 'Ỗ' => 'Ỗ', + 'ỗ' => 'ỗ', + 'Ộ' => 'Ộ', + 'ộ' => 'ộ', + 'Ớ' => 'Ớ', + 'ớ' => 'ớ', + 'Ờ' => 'Ờ', + 'ờ' => 'ờ', + 'Ở' => 'Ở', + 'ở' => 'ở', + 'Ỡ' => 'Ỡ', + 'ỡ' => 'ỡ', + 'Ợ' => 'Ợ', + 'ợ' => 'ợ', + 'Ụ' => 'Ụ', + 'ụ' => 'ụ', + 'Ủ' => 'Ủ', + 'ủ' => 'ủ', + 'Ứ' => 'Ứ', + 'ứ' => 'ứ', + 'Ừ' => 'Ừ', + 'ừ' => 'ừ', + 'Ử' => 'Ử', + 'ử' => 'ử', + 'Ữ' => 'Ữ', + 'ữ' => 'ữ', + 'Ự' => 'Ự', + 'ự' => 'ự', + 'Ỳ' => 'Ỳ', + 'ỳ' => 'ỳ', + 'Ỵ' => 'Ỵ', + 'ỵ' => 'ỵ', + 'Ỷ' => 'Ỷ', + 'ỷ' => 'ỷ', + 'Ỹ' => 'Ỹ', + 'ỹ' => 'ỹ', + 'ἀ' => 'ἀ', + 'ἁ' => 'ἁ', + 'ἂ' => 'ἂ', + 'ἃ' => 'ἃ', + 'ἄ' => 'ἄ', + 'ἅ' => 'ἅ', + 'ἆ' => 'ἆ', + 'ἇ' => 'ἇ', + 'Ἀ' => 'Ἀ', + 'Ἁ' => 'Ἁ', + 'Ἂ' => 'Ἂ', + 'Ἃ' => 'Ἃ', + 'Ἄ' => 'Ἄ', + 'Ἅ' => 'Ἅ', + 'Ἆ' => 'Ἆ', + 'Ἇ' => 'Ἇ', + 'ἐ' => 'ἐ', + 'ἑ' => 'ἑ', + 'ἒ' => 'ἒ', + 'ἓ' => 'ἓ', + 'ἔ' => 'ἔ', + 'ἕ' => 'ἕ', + 'Ἐ' => 'Ἐ', + 'Ἑ' => 'Ἑ', + 'Ἒ' => 'Ἒ', + 'Ἓ' => 'Ἓ', + 'Ἔ' => 'Ἔ', + 'Ἕ' => 'Ἕ', + 'ἠ' => 'ἠ', + 'ἡ' => 'ἡ', + 'ἢ' => 'ἢ', + 'ἣ' => 'ἣ', + 'ἤ' => 'ἤ', + 'ἥ' => 'ἥ', + 'ἦ' => 'ἦ', + 'ἧ' => 'ἧ', + 'Ἠ' => 'Ἠ', + 'Ἡ' => 'Ἡ', + 'Ἢ' => 'Ἢ', + 'Ἣ' => 'Ἣ', + 'Ἤ' => 'Ἤ', + 'Ἥ' => 'Ἥ', + 'Ἦ' => 'Ἦ', + 'Ἧ' => 'Ἧ', + 'ἰ' => 'ἰ', + 'ἱ' => 'ἱ', + 'ἲ' => 'ἲ', + 'ἳ' => 'ἳ', + 'ἴ' => 'ἴ', + 'ἵ' => 'ἵ', + 'ἶ' => 'ἶ', + 'ἷ' => 'ἷ', + 'Ἰ' => 'Ἰ', + 'Ἱ' => 'Ἱ', + 'Ἲ' => 'Ἲ', + 'Ἳ' => 'Ἳ', + 'Ἴ' => 'Ἴ', + 'Ἵ' => 'Ἵ', + 'Ἶ' => 'Ἶ', + 'Ἷ' => 'Ἷ', + 'ὀ' => 'ὀ', + 'ὁ' => 'ὁ', + 'ὂ' => 'ὂ', + 'ὃ' => 'ὃ', + 'ὄ' => 'ὄ', + 'ὅ' => 'ὅ', + 'Ὀ' => 'Ὀ', + 'Ὁ' => 'Ὁ', + 'Ὂ' => 'Ὂ', + 'Ὃ' => 'Ὃ', + 'Ὄ' => 'Ὄ', + 'Ὅ' => 'Ὅ', + 'ὐ' => 'ὐ', + 'ὑ' => 'ὑ', + 'ὒ' => 'ὒ', + 'ὓ' => 'ὓ', + 'ὔ' => 'ὔ', + 'ὕ' => 'ὕ', + 'ὖ' => 'ὖ', + 'ὗ' => 'ὗ', + 'Ὑ' => 'Ὑ', + 'Ὓ' => 'Ὓ', + 'Ὕ' => 'Ὕ', + 'Ὗ' => 'Ὗ', + 'ὠ' => 'ὠ', + 'ὡ' => 'ὡ', + 'ὢ' => 'ὢ', + 'ὣ' => 'ὣ', + 'ὤ' => 'ὤ', + 'ὥ' => 'ὥ', + 'ὦ' => 'ὦ', + 'ὧ' => 'ὧ', + 'Ὠ' => 'Ὠ', + 'Ὡ' => 'Ὡ', + 'Ὢ' => 'Ὢ', + 'Ὣ' => 'Ὣ', + 'Ὤ' => 'Ὤ', + 'Ὥ' => 'Ὥ', + 'Ὦ' => 'Ὦ', + 'Ὧ' => 'Ὧ', + 'ὰ' => 'ὰ', + 'ὲ' => 'ὲ', + 'ὴ' => 'ὴ', + 'ὶ' => 'ὶ', + 'ὸ' => 'ὸ', + 'ὺ' => 'ὺ', + 'ὼ' => 'ὼ', + 'ᾀ' => 'ᾀ', + 'ᾁ' => 'ᾁ', + 'ᾂ' => 'ᾂ', + 'ᾃ' => 'ᾃ', + 'ᾄ' => 'ᾄ', + 'ᾅ' => 'ᾅ', + 'ᾆ' => 'ᾆ', + 'ᾇ' => 'ᾇ', + 'ᾈ' => 'ᾈ', + 'ᾉ' => 'ᾉ', + 'ᾊ' => 'ᾊ', + 'ᾋ' => 'ᾋ', + 'ᾌ' => 'ᾌ', + 'ᾍ' => 'ᾍ', + 'ᾎ' => 'ᾎ', + 'ᾏ' => 'ᾏ', + 'ᾐ' => 'ᾐ', + 'ᾑ' => 'ᾑ', + 'ᾒ' => 'ᾒ', + 'ᾓ' => 'ᾓ', + 'ᾔ' => 'ᾔ', + 'ᾕ' => 'ᾕ', + 'ᾖ' => 'ᾖ', + 'ᾗ' => 'ᾗ', + 'ᾘ' => 'ᾘ', + 'ᾙ' => 'ᾙ', + 'ᾚ' => 'ᾚ', + 'ᾛ' => 'ᾛ', + 'ᾜ' => 'ᾜ', + 'ᾝ' => 'ᾝ', + 'ᾞ' => 'ᾞ', + 'ᾟ' => 'ᾟ', + 'ᾠ' => 'ᾠ', + 'ᾡ' => 'ᾡ', + 'ᾢ' => 'ᾢ', + 'ᾣ' => 'ᾣ', + 'ᾤ' => 'ᾤ', + 'ᾥ' => 'ᾥ', + 'ᾦ' => 'ᾦ', + 'ᾧ' => 'ᾧ', + 'ᾨ' => 'ᾨ', + 'ᾩ' => 'ᾩ', + 'ᾪ' => 'ᾪ', + 'ᾫ' => 'ᾫ', + 'ᾬ' => 'ᾬ', + 'ᾭ' => 'ᾭ', + 'ᾮ' => 'ᾮ', + 'ᾯ' => 'ᾯ', + 'ᾰ' => 'ᾰ', + 'ᾱ' => 'ᾱ', + 'ᾲ' => 'ᾲ', + 'ᾳ' => 'ᾳ', + 'ᾴ' => 'ᾴ', + 'ᾶ' => 'ᾶ', + 'ᾷ' => 'ᾷ', + 'Ᾰ' => 'Ᾰ', + 'Ᾱ' => 'Ᾱ', + 'Ὰ' => 'Ὰ', + 'ᾼ' => 'ᾼ', + '῁' => '῁', + 'ῂ' => 'ῂ', + 'ῃ' => 'ῃ', + 'ῄ' => 'ῄ', + 'ῆ' => 'ῆ', + 'ῇ' => 'ῇ', + 'Ὲ' => 'Ὲ', + 'Ὴ' => 'Ὴ', + 'ῌ' => 'ῌ', + '῍' => '῍', + '῎' => '῎', + '῏' => '῏', + 'ῐ' => 'ῐ', + 'ῑ' => 'ῑ', + 'ῒ' => 'ῒ', + 'ῖ' => 'ῖ', + 'ῗ' => 'ῗ', + 'Ῐ' => 'Ῐ', + 'Ῑ' => 'Ῑ', + 'Ὶ' => 'Ὶ', + '῝' => '῝', + '῞' => '῞', + '῟' => '῟', + 'ῠ' => 'ῠ', + 'ῡ' => 'ῡ', + 'ῢ' => 'ῢ', + 'ῤ' => 'ῤ', + 'ῥ' => 'ῥ', + 'ῦ' => 'ῦ', + 'ῧ' => 'ῧ', + 'Ῠ' => 'Ῠ', + 'Ῡ' => 'Ῡ', + 'Ὺ' => 'Ὺ', + 'Ῥ' => 'Ῥ', + '῭' => '῭', + 'ῲ' => 'ῲ', + 'ῳ' => 'ῳ', + 'ῴ' => 'ῴ', + 'ῶ' => 'ῶ', + 'ῷ' => 'ῷ', + 'Ὸ' => 'Ὸ', + 'Ὼ' => 'Ὼ', + 'ῼ' => 'ῼ', + '↚' => '↚', + '↛' => '↛', + '↮' => '↮', + '⇍' => '⇍', + '⇎' => '⇎', + '⇏' => '⇏', + '∄' => '∄', + '∉' => '∉', + '∌' => '∌', + '∤' => '∤', + '∦' => '∦', + '≁' => '≁', + '≄' => '≄', + '≇' => '≇', + '≉' => '≉', + '≠' => '≠', + '≢' => '≢', + '≭' => '≭', + '≮' => '≮', + '≯' => '≯', + '≰' => '≰', + '≱' => '≱', + '≴' => '≴', + '≵' => '≵', + '≸' => '≸', + '≹' => '≹', + '⊀' => '⊀', + '⊁' => '⊁', + '⊄' => '⊄', + '⊅' => '⊅', + '⊈' => '⊈', + '⊉' => '⊉', + '⊬' => '⊬', + '⊭' => '⊭', + '⊮' => '⊮', + '⊯' => '⊯', + '⋠' => '⋠', + '⋡' => '⋡', + '⋢' => '⋢', + '⋣' => '⋣', + '⋪' => '⋪', + '⋫' => '⋫', + '⋬' => '⋬', + '⋭' => '⋭', + 'が' => 'が', + 'ぎ' => 'ぎ', + 'ぐ' => 'ぐ', + 'げ' => 'げ', + 'ご' => 'ご', + 'ざ' => 'ざ', + 'じ' => 'じ', + 'ず' => 'ず', + 'ぜ' => 'ぜ', + 'ぞ' => 'ぞ', + 'だ' => 'だ', + 'ぢ' => 'ぢ', + 'づ' => 'づ', + 'で' => 'で', + 'ど' => 'ど', + 'ば' => 'ば', + 'ぱ' => 'ぱ', + 'び' => 'び', + 'ぴ' => 'ぴ', + 'ぶ' => 'ぶ', + 'ぷ' => 'ぷ', + 'べ' => 'べ', + 'ぺ' => 'ぺ', + 'ぼ' => 'ぼ', + 'ぽ' => 'ぽ', + 'ゔ' => 'ゔ', + 'ゞ' => 'ゞ', + 'ガ' => 'ガ', + 'ギ' => 'ギ', + 'グ' => 'グ', + 'ゲ' => 'ゲ', + 'ゴ' => 'ゴ', + 'ザ' => 'ザ', + 'ジ' => 'ジ', + 'ズ' => 'ズ', + 'ゼ' => 'ゼ', + 'ゾ' => 'ゾ', + 'ダ' => 'ダ', + 'ヂ' => 'ヂ', + 'ヅ' => 'ヅ', + 'デ' => 'デ', + 'ド' => 'ド', + 'バ' => 'バ', + 'パ' => 'パ', + 'ビ' => 'ビ', + 'ピ' => 'ピ', + 'ブ' => 'ブ', + 'プ' => 'プ', + 'ベ' => 'ベ', + 'ペ' => 'ペ', + 'ボ' => 'ボ', + 'ポ' => 'ポ', + 'ヴ' => 'ヴ', + 'ヷ' => 'ヷ', + 'ヸ' => 'ヸ', + 'ヹ' => 'ヹ', + 'ヺ' => 'ヺ', + 'ヾ' => 'ヾ', + '𑂚' => '𑂚', + '𑂜' => '𑂜', + '𑂫' => '𑂫', + '𑄮' => '𑄮', + '𑄯' => '𑄯', + '𑍋' => '𑍋', + '𑍌' => '𑍌', + '𑒻' => '𑒻', + '𑒼' => '𑒼', + '𑒾' => '𑒾', + '𑖺' => '𑖺', + '𑖻' => '𑖻', + '𑤸' => '𑤸', +); diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php new file mode 100644 index 0000000..5a3e8e0 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php @@ -0,0 +1,2065 @@ + 'À', + 'Á' => 'Á', + 'Â' => 'Â', + 'Ã' => 'Ã', + 'Ä' => 'Ä', + 'Å' => 'Å', + 'Ç' => 'Ç', + 'È' => 'È', + 'É' => 'É', + 'Ê' => 'Ê', + 'Ë' => 'Ë', + 'Ì' => 'Ì', + 'Í' => 'Í', + 'Î' => 'Î', + 'Ï' => 'Ï', + 'Ñ' => 'Ñ', + 'Ò' => 'Ò', + 'Ó' => 'Ó', + 'Ô' => 'Ô', + 'Õ' => 'Õ', + 'Ö' => 'Ö', + 'Ù' => 'Ù', + 'Ú' => 'Ú', + 'Û' => 'Û', + 'Ü' => 'Ü', + 'Ý' => 'Ý', + 'à' => 'à', + 'á' => 'á', + 'â' => 'â', + 'ã' => 'ã', + 'ä' => 'ä', + 'å' => 'å', + 'ç' => 'ç', + 'è' => 'è', + 'é' => 'é', + 'ê' => 'ê', + 'ë' => 'ë', + 'ì' => 'ì', + 'í' => 'í', + 'î' => 'î', + 'ï' => 'ï', + 'ñ' => 'ñ', + 'ò' => 'ò', + 'ó' => 'ó', + 'ô' => 'ô', + 'õ' => 'õ', + 'ö' => 'ö', + 'ù' => 'ù', + 'ú' => 'ú', + 'û' => 'û', + 'ü' => 'ü', + 'ý' => 'ý', + 'ÿ' => 'ÿ', + 'Ā' => 'Ā', + 'ā' => 'ā', + 'Ă' => 'Ă', + 'ă' => 'ă', + 'Ą' => 'Ą', + 'ą' => 'ą', + 'Ć' => 'Ć', + 'ć' => 'ć', + 'Ĉ' => 'Ĉ', + 'ĉ' => 'ĉ', + 'Ċ' => 'Ċ', + 'ċ' => 'ċ', + 'Č' => 'Č', + 'č' => 'č', + 'Ď' => 'Ď', + 'ď' => 'ď', + 'Ē' => 'Ē', + 'ē' => 'ē', + 'Ĕ' => 'Ĕ', + 'ĕ' => 'ĕ', + 'Ė' => 'Ė', + 'ė' => 'ė', + 'Ę' => 'Ę', + 'ę' => 'ę', + 'Ě' => 'Ě', + 'ě' => 'ě', + 'Ĝ' => 'Ĝ', + 'ĝ' => 'ĝ', + 'Ğ' => 'Ğ', + 'ğ' => 'ğ', + 'Ġ' => 'Ġ', + 'ġ' => 'ġ', + 'Ģ' => 'Ģ', + 'ģ' => 'ģ', + 'Ĥ' => 'Ĥ', + 'ĥ' => 'ĥ', + 'Ĩ' => 'Ĩ', + 'ĩ' => 'ĩ', + 'Ī' => 'Ī', + 'ī' => 'ī', + 'Ĭ' => 'Ĭ', + 'ĭ' => 'ĭ', + 'Į' => 'Į', + 'į' => 'į', + 'İ' => 'İ', + 'Ĵ' => 'Ĵ', + 'ĵ' => 'ĵ', + 'Ķ' => 'Ķ', + 'ķ' => 'ķ', + 'Ĺ' => 'Ĺ', + 'ĺ' => 'ĺ', + 'Ļ' => 'Ļ', + 'ļ' => 'ļ', + 'Ľ' => 'Ľ', + 'ľ' => 'ľ', + 'Ń' => 'Ń', + 'ń' => 'ń', + 'Ņ' => 'Ņ', + 'ņ' => 'ņ', + 'Ň' => 'Ň', + 'ň' => 'ň', + 'Ō' => 'Ō', + 'ō' => 'ō', + 'Ŏ' => 'Ŏ', + 'ŏ' => 'ŏ', + 'Ő' => 'Ő', + 'ő' => 'ő', + 'Ŕ' => 'Ŕ', + 'ŕ' => 'ŕ', + 'Ŗ' => 'Ŗ', + 'ŗ' => 'ŗ', + 'Ř' => 'Ř', + 'ř' => 'ř', + 'Ś' => 'Ś', + 'ś' => 'ś', + 'Ŝ' => 'Ŝ', + 'ŝ' => 'ŝ', + 'Ş' => 'Ş', + 'ş' => 'ş', + 'Š' => 'Š', + 'š' => 'š', + 'Ţ' => 'Ţ', + 'ţ' => 'ţ', + 'Ť' => 'Ť', + 'ť' => 'ť', + 'Ũ' => 'Ũ', + 'ũ' => 'ũ', + 'Ū' => 'Ū', + 'ū' => 'ū', + 'Ŭ' => 'Ŭ', + 'ŭ' => 'ŭ', + 'Ů' => 'Ů', + 'ů' => 'ů', + 'Ű' => 'Ű', + 'ű' => 'ű', + 'Ų' => 'Ų', + 'ų' => 'ų', + 'Ŵ' => 'Ŵ', + 'ŵ' => 'ŵ', + 'Ŷ' => 'Ŷ', + 'ŷ' => 'ŷ', + 'Ÿ' => 'Ÿ', + 'Ź' => 'Ź', + 'ź' => 'ź', + 'Ż' => 'Ż', + 'ż' => 'ż', + 'Ž' => 'Ž', + 'ž' => 'ž', + 'Ơ' => 'Ơ', + 'ơ' => 'ơ', + 'Ư' => 'Ư', + 'ư' => 'ư', + 'Ǎ' => 'Ǎ', + 'ǎ' => 'ǎ', + 'Ǐ' => 'Ǐ', + 'ǐ' => 'ǐ', + 'Ǒ' => 'Ǒ', + 'ǒ' => 'ǒ', + 'Ǔ' => 'Ǔ', + 'ǔ' => 'ǔ', + 'Ǖ' => 'Ǖ', + 'ǖ' => 'ǖ', + 'Ǘ' => 'Ǘ', + 'ǘ' => 'ǘ', + 'Ǚ' => 'Ǚ', + 'ǚ' => 'ǚ', + 'Ǜ' => 'Ǜ', + 'ǜ' => 'ǜ', + 'Ǟ' => 'Ǟ', + 'ǟ' => 'ǟ', + 'Ǡ' => 'Ǡ', + 'ǡ' => 'ǡ', + 'Ǣ' => 'Ǣ', + 'ǣ' => 'ǣ', + 'Ǧ' => 'Ǧ', + 'ǧ' => 'ǧ', + 'Ǩ' => 'Ǩ', + 'ǩ' => 'ǩ', + 'Ǫ' => 'Ǫ', + 'ǫ' => 'ǫ', + 'Ǭ' => 'Ǭ', + 'ǭ' => 'ǭ', + 'Ǯ' => 'Ǯ', + 'ǯ' => 'ǯ', + 'ǰ' => 'ǰ', + 'Ǵ' => 'Ǵ', + 'ǵ' => 'ǵ', + 'Ǹ' => 'Ǹ', + 'ǹ' => 'ǹ', + 'Ǻ' => 'Ǻ', + 'ǻ' => 'ǻ', + 'Ǽ' => 'Ǽ', + 'ǽ' => 'ǽ', + 'Ǿ' => 'Ǿ', + 'ǿ' => 'ǿ', + 'Ȁ' => 'Ȁ', + 'ȁ' => 'ȁ', + 'Ȃ' => 'Ȃ', + 'ȃ' => 'ȃ', + 'Ȅ' => 'Ȅ', + 'ȅ' => 'ȅ', + 'Ȇ' => 'Ȇ', + 'ȇ' => 'ȇ', + 'Ȉ' => 'Ȉ', + 'ȉ' => 'ȉ', + 'Ȋ' => 'Ȋ', + 'ȋ' => 'ȋ', + 'Ȍ' => 'Ȍ', + 'ȍ' => 'ȍ', + 'Ȏ' => 'Ȏ', + 'ȏ' => 'ȏ', + 'Ȑ' => 'Ȑ', + 'ȑ' => 'ȑ', + 'Ȓ' => 'Ȓ', + 'ȓ' => 'ȓ', + 'Ȕ' => 'Ȕ', + 'ȕ' => 'ȕ', + 'Ȗ' => 'Ȗ', + 'ȗ' => 'ȗ', + 'Ș' => 'Ș', + 'ș' => 'ș', + 'Ț' => 'Ț', + 'ț' => 'ț', + 'Ȟ' => 'Ȟ', + 'ȟ' => 'ȟ', + 'Ȧ' => 'Ȧ', + 'ȧ' => 'ȧ', + 'Ȩ' => 'Ȩ', + 'ȩ' => 'ȩ', + 'Ȫ' => 'Ȫ', + 'ȫ' => 'ȫ', + 'Ȭ' => 'Ȭ', + 'ȭ' => 'ȭ', + 'Ȯ' => 'Ȯ', + 'ȯ' => 'ȯ', + 'Ȱ' => 'Ȱ', + 'ȱ' => 'ȱ', + 'Ȳ' => 'Ȳ', + 'ȳ' => 'ȳ', + '̀' => '̀', + '́' => '́', + '̓' => '̓', + '̈́' => '̈́', + 'ʹ' => 'ʹ', + ';' => ';', + '΅' => '΅', + 'Ά' => 'Ά', + '·' => '·', + 'Έ' => 'Έ', + 'Ή' => 'Ή', + 'Ί' => 'Ί', + 'Ό' => 'Ό', + 'Ύ' => 'Ύ', + 'Ώ' => 'Ώ', + 'ΐ' => 'ΐ', + 'Ϊ' => 'Ϊ', + 'Ϋ' => 'Ϋ', + 'ά' => 'ά', + 'έ' => 'έ', + 'ή' => 'ή', + 'ί' => 'ί', + 'ΰ' => 'ΰ', + 'ϊ' => 'ϊ', + 'ϋ' => 'ϋ', + 'ό' => 'ό', + 'ύ' => 'ύ', + 'ώ' => 'ώ', + 'ϓ' => 'ϓ', + 'ϔ' => 'ϔ', + 'Ѐ' => 'Ѐ', + 'Ё' => 'Ё', + 'Ѓ' => 'Ѓ', + 'Ї' => 'Ї', + 'Ќ' => 'Ќ', + 'Ѝ' => 'Ѝ', + 'Ў' => 'Ў', + 'Й' => 'Й', + 'й' => 'й', + 'ѐ' => 'ѐ', + 'ё' => 'ё', + 'ѓ' => 'ѓ', + 'ї' => 'ї', + 'ќ' => 'ќ', + 'ѝ' => 'ѝ', + 'ў' => 'ў', + 'Ѷ' => 'Ѷ', + 'ѷ' => 'ѷ', + 'Ӂ' => 'Ӂ', + 'ӂ' => 'ӂ', + 'Ӑ' => 'Ӑ', + 'ӑ' => 'ӑ', + 'Ӓ' => 'Ӓ', + 'ӓ' => 'ӓ', + 'Ӗ' => 'Ӗ', + 'ӗ' => 'ӗ', + 'Ӛ' => 'Ӛ', + 'ӛ' => 'ӛ', + 'Ӝ' => 'Ӝ', + 'ӝ' => 'ӝ', + 'Ӟ' => 'Ӟ', + 'ӟ' => 'ӟ', + 'Ӣ' => 'Ӣ', + 'ӣ' => 'ӣ', + 'Ӥ' => 'Ӥ', + 'ӥ' => 'ӥ', + 'Ӧ' => 'Ӧ', + 'ӧ' => 'ӧ', + 'Ӫ' => 'Ӫ', + 'ӫ' => 'ӫ', + 'Ӭ' => 'Ӭ', + 'ӭ' => 'ӭ', + 'Ӯ' => 'Ӯ', + 'ӯ' => 'ӯ', + 'Ӱ' => 'Ӱ', + 'ӱ' => 'ӱ', + 'Ӳ' => 'Ӳ', + 'ӳ' => 'ӳ', + 'Ӵ' => 'Ӵ', + 'ӵ' => 'ӵ', + 'Ӹ' => 'Ӹ', + 'ӹ' => 'ӹ', + 'آ' => 'آ', + 'أ' => 'أ', + 'ؤ' => 'ؤ', + 'إ' => 'إ', + 'ئ' => 'ئ', + 'ۀ' => 'ۀ', + 'ۂ' => 'ۂ', + 'ۓ' => 'ۓ', + 'ऩ' => 'ऩ', + 'ऱ' => 'ऱ', + 'ऴ' => 'ऴ', + 'क़' => 'क़', + 'ख़' => 'ख़', + 'ग़' => 'ग़', + 'ज़' => 'ज़', + 'ड़' => 'ड़', + 'ढ़' => 'ढ़', + 'फ़' => 'फ़', + 'य़' => 'य़', + 'ো' => 'ো', + 'ৌ' => 'ৌ', + 'ড়' => 'ড়', + 'ঢ়' => 'ঢ়', + 'য়' => 'য়', + 'ਲ਼' => 'ਲ਼', + 'ਸ਼' => 'ਸ਼', + 'ਖ਼' => 'ਖ਼', + 'ਗ਼' => 'ਗ਼', + 'ਜ਼' => 'ਜ਼', + 'ਫ਼' => 'ਫ਼', + 'ୈ' => 'ୈ', + 'ୋ' => 'ୋ', + 'ୌ' => 'ୌ', + 'ଡ଼' => 'ଡ଼', + 'ଢ଼' => 'ଢ଼', + 'ஔ' => 'ஔ', + 'ொ' => 'ொ', + 'ோ' => 'ோ', + 'ௌ' => 'ௌ', + 'ై' => 'ై', + 'ೀ' => 'ೀ', + 'ೇ' => 'ೇ', + 'ೈ' => 'ೈ', + 'ೊ' => 'ೊ', + 'ೋ' => 'ೋ', + 'ൊ' => 'ൊ', + 'ോ' => 'ോ', + 'ൌ' => 'ൌ', + 'ේ' => 'ේ', + 'ො' => 'ො', + 'ෝ' => 'ෝ', + 'ෞ' => 'ෞ', + 'གྷ' => 'གྷ', + 'ཌྷ' => 'ཌྷ', + 'དྷ' => 'དྷ', + 'བྷ' => 'བྷ', + 'ཛྷ' => 'ཛྷ', + 'ཀྵ' => 'ཀྵ', + 'ཱི' => 'ཱི', + 'ཱུ' => 'ཱུ', + 'ྲྀ' => 'ྲྀ', + 'ླྀ' => 'ླྀ', + 'ཱྀ' => 'ཱྀ', + 'ྒྷ' => 'ྒྷ', + 'ྜྷ' => 'ྜྷ', + 'ྡྷ' => 'ྡྷ', + 'ྦྷ' => 'ྦྷ', + 'ྫྷ' => 'ྫྷ', + 'ྐྵ' => 'ྐྵ', + 'ဦ' => 'ဦ', + 'ᬆ' => 'ᬆ', + 'ᬈ' => 'ᬈ', + 'ᬊ' => 'ᬊ', + 'ᬌ' => 'ᬌ', + 'ᬎ' => 'ᬎ', + 'ᬒ' => 'ᬒ', + 'ᬻ' => 'ᬻ', + 'ᬽ' => 'ᬽ', + 'ᭀ' => 'ᭀ', + 'ᭁ' => 'ᭁ', + 'ᭃ' => 'ᭃ', + 'Ḁ' => 'Ḁ', + 'ḁ' => 'ḁ', + 'Ḃ' => 'Ḃ', + 'ḃ' => 'ḃ', + 'Ḅ' => 'Ḅ', + 'ḅ' => 'ḅ', + 'Ḇ' => 'Ḇ', + 'ḇ' => 'ḇ', + 'Ḉ' => 'Ḉ', + 'ḉ' => 'ḉ', + 'Ḋ' => 'Ḋ', + 'ḋ' => 'ḋ', + 'Ḍ' => 'Ḍ', + 'ḍ' => 'ḍ', + 'Ḏ' => 'Ḏ', + 'ḏ' => 'ḏ', + 'Ḑ' => 'Ḑ', + 'ḑ' => 'ḑ', + 'Ḓ' => 'Ḓ', + 'ḓ' => 'ḓ', + 'Ḕ' => 'Ḕ', + 'ḕ' => 'ḕ', + 'Ḗ' => 'Ḗ', + 'ḗ' => 'ḗ', + 'Ḙ' => 'Ḙ', + 'ḙ' => 'ḙ', + 'Ḛ' => 'Ḛ', + 'ḛ' => 'ḛ', + 'Ḝ' => 'Ḝ', + 'ḝ' => 'ḝ', + 'Ḟ' => 'Ḟ', + 'ḟ' => 'ḟ', + 'Ḡ' => 'Ḡ', + 'ḡ' => 'ḡ', + 'Ḣ' => 'Ḣ', + 'ḣ' => 'ḣ', + 'Ḥ' => 'Ḥ', + 'ḥ' => 'ḥ', + 'Ḧ' => 'Ḧ', + 'ḧ' => 'ḧ', + 'Ḩ' => 'Ḩ', + 'ḩ' => 'ḩ', + 'Ḫ' => 'Ḫ', + 'ḫ' => 'ḫ', + 'Ḭ' => 'Ḭ', + 'ḭ' => 'ḭ', + 'Ḯ' => 'Ḯ', + 'ḯ' => 'ḯ', + 'Ḱ' => 'Ḱ', + 'ḱ' => 'ḱ', + 'Ḳ' => 'Ḳ', + 'ḳ' => 'ḳ', + 'Ḵ' => 'Ḵ', + 'ḵ' => 'ḵ', + 'Ḷ' => 'Ḷ', + 'ḷ' => 'ḷ', + 'Ḹ' => 'Ḹ', + 'ḹ' => 'ḹ', + 'Ḻ' => 'Ḻ', + 'ḻ' => 'ḻ', + 'Ḽ' => 'Ḽ', + 'ḽ' => 'ḽ', + 'Ḿ' => 'Ḿ', + 'ḿ' => 'ḿ', + 'Ṁ' => 'Ṁ', + 'ṁ' => 'ṁ', + 'Ṃ' => 'Ṃ', + 'ṃ' => 'ṃ', + 'Ṅ' => 'Ṅ', + 'ṅ' => 'ṅ', + 'Ṇ' => 'Ṇ', + 'ṇ' => 'ṇ', + 'Ṉ' => 'Ṉ', + 'ṉ' => 'ṉ', + 'Ṋ' => 'Ṋ', + 'ṋ' => 'ṋ', + 'Ṍ' => 'Ṍ', + 'ṍ' => 'ṍ', + 'Ṏ' => 'Ṏ', + 'ṏ' => 'ṏ', + 'Ṑ' => 'Ṑ', + 'ṑ' => 'ṑ', + 'Ṓ' => 'Ṓ', + 'ṓ' => 'ṓ', + 'Ṕ' => 'Ṕ', + 'ṕ' => 'ṕ', + 'Ṗ' => 'Ṗ', + 'ṗ' => 'ṗ', + 'Ṙ' => 'Ṙ', + 'ṙ' => 'ṙ', + 'Ṛ' => 'Ṛ', + 'ṛ' => 'ṛ', + 'Ṝ' => 'Ṝ', + 'ṝ' => 'ṝ', + 'Ṟ' => 'Ṟ', + 'ṟ' => 'ṟ', + 'Ṡ' => 'Ṡ', + 'ṡ' => 'ṡ', + 'Ṣ' => 'Ṣ', + 'ṣ' => 'ṣ', + 'Ṥ' => 'Ṥ', + 'ṥ' => 'ṥ', + 'Ṧ' => 'Ṧ', + 'ṧ' => 'ṧ', + 'Ṩ' => 'Ṩ', + 'ṩ' => 'ṩ', + 'Ṫ' => 'Ṫ', + 'ṫ' => 'ṫ', + 'Ṭ' => 'Ṭ', + 'ṭ' => 'ṭ', + 'Ṯ' => 'Ṯ', + 'ṯ' => 'ṯ', + 'Ṱ' => 'Ṱ', + 'ṱ' => 'ṱ', + 'Ṳ' => 'Ṳ', + 'ṳ' => 'ṳ', + 'Ṵ' => 'Ṵ', + 'ṵ' => 'ṵ', + 'Ṷ' => 'Ṷ', + 'ṷ' => 'ṷ', + 'Ṹ' => 'Ṹ', + 'ṹ' => 'ṹ', + 'Ṻ' => 'Ṻ', + 'ṻ' => 'ṻ', + 'Ṽ' => 'Ṽ', + 'ṽ' => 'ṽ', + 'Ṿ' => 'Ṿ', + 'ṿ' => 'ṿ', + 'Ẁ' => 'Ẁ', + 'ẁ' => 'ẁ', + 'Ẃ' => 'Ẃ', + 'ẃ' => 'ẃ', + 'Ẅ' => 'Ẅ', + 'ẅ' => 'ẅ', + 'Ẇ' => 'Ẇ', + 'ẇ' => 'ẇ', + 'Ẉ' => 'Ẉ', + 'ẉ' => 'ẉ', + 'Ẋ' => 'Ẋ', + 'ẋ' => 'ẋ', + 'Ẍ' => 'Ẍ', + 'ẍ' => 'ẍ', + 'Ẏ' => 'Ẏ', + 'ẏ' => 'ẏ', + 'Ẑ' => 'Ẑ', + 'ẑ' => 'ẑ', + 'Ẓ' => 'Ẓ', + 'ẓ' => 'ẓ', + 'Ẕ' => 'Ẕ', + 'ẕ' => 'ẕ', + 'ẖ' => 'ẖ', + 'ẗ' => 'ẗ', + 'ẘ' => 'ẘ', + 'ẙ' => 'ẙ', + 'ẛ' => 'ẛ', + 'Ạ' => 'Ạ', + 'ạ' => 'ạ', + 'Ả' => 'Ả', + 'ả' => 'ả', + 'Ấ' => 'Ấ', + 'ấ' => 'ấ', + 'Ầ' => 'Ầ', + 'ầ' => 'ầ', + 'Ẩ' => 'Ẩ', + 'ẩ' => 'ẩ', + 'Ẫ' => 'Ẫ', + 'ẫ' => 'ẫ', + 'Ậ' => 'Ậ', + 'ậ' => 'ậ', + 'Ắ' => 'Ắ', + 'ắ' => 'ắ', + 'Ằ' => 'Ằ', + 'ằ' => 'ằ', + 'Ẳ' => 'Ẳ', + 'ẳ' => 'ẳ', + 'Ẵ' => 'Ẵ', + 'ẵ' => 'ẵ', + 'Ặ' => 'Ặ', + 'ặ' => 'ặ', + 'Ẹ' => 'Ẹ', + 'ẹ' => 'ẹ', + 'Ẻ' => 'Ẻ', + 'ẻ' => 'ẻ', + 'Ẽ' => 'Ẽ', + 'ẽ' => 'ẽ', + 'Ế' => 'Ế', + 'ế' => 'ế', + 'Ề' => 'Ề', + 'ề' => 'ề', + 'Ể' => 'Ể', + 'ể' => 'ể', + 'Ễ' => 'Ễ', + 'ễ' => 'ễ', + 'Ệ' => 'Ệ', + 'ệ' => 'ệ', + 'Ỉ' => 'Ỉ', + 'ỉ' => 'ỉ', + 'Ị' => 'Ị', + 'ị' => 'ị', + 'Ọ' => 'Ọ', + 'ọ' => 'ọ', + 'Ỏ' => 'Ỏ', + 'ỏ' => 'ỏ', + 'Ố' => 'Ố', + 'ố' => 'ố', + 'Ồ' => 'Ồ', + 'ồ' => 'ồ', + 'Ổ' => 'Ổ', + 'ổ' => 'ổ', + 'Ỗ' => 'Ỗ', + 'ỗ' => 'ỗ', + 'Ộ' => 'Ộ', + 'ộ' => 'ộ', + 'Ớ' => 'Ớ', + 'ớ' => 'ớ', + 'Ờ' => 'Ờ', + 'ờ' => 'ờ', + 'Ở' => 'Ở', + 'ở' => 'ở', + 'Ỡ' => 'Ỡ', + 'ỡ' => 'ỡ', + 'Ợ' => 'Ợ', + 'ợ' => 'ợ', + 'Ụ' => 'Ụ', + 'ụ' => 'ụ', + 'Ủ' => 'Ủ', + 'ủ' => 'ủ', + 'Ứ' => 'Ứ', + 'ứ' => 'ứ', + 'Ừ' => 'Ừ', + 'ừ' => 'ừ', + 'Ử' => 'Ử', + 'ử' => 'ử', + 'Ữ' => 'Ữ', + 'ữ' => 'ữ', + 'Ự' => 'Ự', + 'ự' => 'ự', + 'Ỳ' => 'Ỳ', + 'ỳ' => 'ỳ', + 'Ỵ' => 'Ỵ', + 'ỵ' => 'ỵ', + 'Ỷ' => 'Ỷ', + 'ỷ' => 'ỷ', + 'Ỹ' => 'Ỹ', + 'ỹ' => 'ỹ', + 'ἀ' => 'ἀ', + 'ἁ' => 'ἁ', + 'ἂ' => 'ἂ', + 'ἃ' => 'ἃ', + 'ἄ' => 'ἄ', + 'ἅ' => 'ἅ', + 'ἆ' => 'ἆ', + 'ἇ' => 'ἇ', + 'Ἀ' => 'Ἀ', + 'Ἁ' => 'Ἁ', + 'Ἂ' => 'Ἂ', + 'Ἃ' => 'Ἃ', + 'Ἄ' => 'Ἄ', + 'Ἅ' => 'Ἅ', + 'Ἆ' => 'Ἆ', + 'Ἇ' => 'Ἇ', + 'ἐ' => 'ἐ', + 'ἑ' => 'ἑ', + 'ἒ' => 'ἒ', + 'ἓ' => 'ἓ', + 'ἔ' => 'ἔ', + 'ἕ' => 'ἕ', + 'Ἐ' => 'Ἐ', + 'Ἑ' => 'Ἑ', + 'Ἒ' => 'Ἒ', + 'Ἓ' => 'Ἓ', + 'Ἔ' => 'Ἔ', + 'Ἕ' => 'Ἕ', + 'ἠ' => 'ἠ', + 'ἡ' => 'ἡ', + 'ἢ' => 'ἢ', + 'ἣ' => 'ἣ', + 'ἤ' => 'ἤ', + 'ἥ' => 'ἥ', + 'ἦ' => 'ἦ', + 'ἧ' => 'ἧ', + 'Ἠ' => 'Ἠ', + 'Ἡ' => 'Ἡ', + 'Ἢ' => 'Ἢ', + 'Ἣ' => 'Ἣ', + 'Ἤ' => 'Ἤ', + 'Ἥ' => 'Ἥ', + 'Ἦ' => 'Ἦ', + 'Ἧ' => 'Ἧ', + 'ἰ' => 'ἰ', + 'ἱ' => 'ἱ', + 'ἲ' => 'ἲ', + 'ἳ' => 'ἳ', + 'ἴ' => 'ἴ', + 'ἵ' => 'ἵ', + 'ἶ' => 'ἶ', + 'ἷ' => 'ἷ', + 'Ἰ' => 'Ἰ', + 'Ἱ' => 'Ἱ', + 'Ἲ' => 'Ἲ', + 'Ἳ' => 'Ἳ', + 'Ἴ' => 'Ἴ', + 'Ἵ' => 'Ἵ', + 'Ἶ' => 'Ἶ', + 'Ἷ' => 'Ἷ', + 'ὀ' => 'ὀ', + 'ὁ' => 'ὁ', + 'ὂ' => 'ὂ', + 'ὃ' => 'ὃ', + 'ὄ' => 'ὄ', + 'ὅ' => 'ὅ', + 'Ὀ' => 'Ὀ', + 'Ὁ' => 'Ὁ', + 'Ὂ' => 'Ὂ', + 'Ὃ' => 'Ὃ', + 'Ὄ' => 'Ὄ', + 'Ὅ' => 'Ὅ', + 'ὐ' => 'ὐ', + 'ὑ' => 'ὑ', + 'ὒ' => 'ὒ', + 'ὓ' => 'ὓ', + 'ὔ' => 'ὔ', + 'ὕ' => 'ὕ', + 'ὖ' => 'ὖ', + 'ὗ' => 'ὗ', + 'Ὑ' => 'Ὑ', + 'Ὓ' => 'Ὓ', + 'Ὕ' => 'Ὕ', + 'Ὗ' => 'Ὗ', + 'ὠ' => 'ὠ', + 'ὡ' => 'ὡ', + 'ὢ' => 'ὢ', + 'ὣ' => 'ὣ', + 'ὤ' => 'ὤ', + 'ὥ' => 'ὥ', + 'ὦ' => 'ὦ', + 'ὧ' => 'ὧ', + 'Ὠ' => 'Ὠ', + 'Ὡ' => 'Ὡ', + 'Ὢ' => 'Ὢ', + 'Ὣ' => 'Ὣ', + 'Ὤ' => 'Ὤ', + 'Ὥ' => 'Ὥ', + 'Ὦ' => 'Ὦ', + 'Ὧ' => 'Ὧ', + 'ὰ' => 'ὰ', + 'ά' => 'ά', + 'ὲ' => 'ὲ', + 'έ' => 'έ', + 'ὴ' => 'ὴ', + 'ή' => 'ή', + 'ὶ' => 'ὶ', + 'ί' => 'ί', + 'ὸ' => 'ὸ', + 'ό' => 'ό', + 'ὺ' => 'ὺ', + 'ύ' => 'ύ', + 'ὼ' => 'ὼ', + 'ώ' => 'ώ', + 'ᾀ' => 'ᾀ', + 'ᾁ' => 'ᾁ', + 'ᾂ' => 'ᾂ', + 'ᾃ' => 'ᾃ', + 'ᾄ' => 'ᾄ', + 'ᾅ' => 'ᾅ', + 'ᾆ' => 'ᾆ', + 'ᾇ' => 'ᾇ', + 'ᾈ' => 'ᾈ', + 'ᾉ' => 'ᾉ', + 'ᾊ' => 'ᾊ', + 'ᾋ' => 'ᾋ', + 'ᾌ' => 'ᾌ', + 'ᾍ' => 'ᾍ', + 'ᾎ' => 'ᾎ', + 'ᾏ' => 'ᾏ', + 'ᾐ' => 'ᾐ', + 'ᾑ' => 'ᾑ', + 'ᾒ' => 'ᾒ', + 'ᾓ' => 'ᾓ', + 'ᾔ' => 'ᾔ', + 'ᾕ' => 'ᾕ', + 'ᾖ' => 'ᾖ', + 'ᾗ' => 'ᾗ', + 'ᾘ' => 'ᾘ', + 'ᾙ' => 'ᾙ', + 'ᾚ' => 'ᾚ', + 'ᾛ' => 'ᾛ', + 'ᾜ' => 'ᾜ', + 'ᾝ' => 'ᾝ', + 'ᾞ' => 'ᾞ', + 'ᾟ' => 'ᾟ', + 'ᾠ' => 'ᾠ', + 'ᾡ' => 'ᾡ', + 'ᾢ' => 'ᾢ', + 'ᾣ' => 'ᾣ', + 'ᾤ' => 'ᾤ', + 'ᾥ' => 'ᾥ', + 'ᾦ' => 'ᾦ', + 'ᾧ' => 'ᾧ', + 'ᾨ' => 'ᾨ', + 'ᾩ' => 'ᾩ', + 'ᾪ' => 'ᾪ', + 'ᾫ' => 'ᾫ', + 'ᾬ' => 'ᾬ', + 'ᾭ' => 'ᾭ', + 'ᾮ' => 'ᾮ', + 'ᾯ' => 'ᾯ', + 'ᾰ' => 'ᾰ', + 'ᾱ' => 'ᾱ', + 'ᾲ' => 'ᾲ', + 'ᾳ' => 'ᾳ', + 'ᾴ' => 'ᾴ', + 'ᾶ' => 'ᾶ', + 'ᾷ' => 'ᾷ', + 'Ᾰ' => 'Ᾰ', + 'Ᾱ' => 'Ᾱ', + 'Ὰ' => 'Ὰ', + 'Ά' => 'Ά', + 'ᾼ' => 'ᾼ', + 'ι' => 'ι', + '῁' => '῁', + 'ῂ' => 'ῂ', + 'ῃ' => 'ῃ', + 'ῄ' => 'ῄ', + 'ῆ' => 'ῆ', + 'ῇ' => 'ῇ', + 'Ὲ' => 'Ὲ', + 'Έ' => 'Έ', + 'Ὴ' => 'Ὴ', + 'Ή' => 'Ή', + 'ῌ' => 'ῌ', + '῍' => '῍', + '῎' => '῎', + '῏' => '῏', + 'ῐ' => 'ῐ', + 'ῑ' => 'ῑ', + 'ῒ' => 'ῒ', + 'ΐ' => 'ΐ', + 'ῖ' => 'ῖ', + 'ῗ' => 'ῗ', + 'Ῐ' => 'Ῐ', + 'Ῑ' => 'Ῑ', + 'Ὶ' => 'Ὶ', + 'Ί' => 'Ί', + '῝' => '῝', + '῞' => '῞', + '῟' => '῟', + 'ῠ' => 'ῠ', + 'ῡ' => 'ῡ', + 'ῢ' => 'ῢ', + 'ΰ' => 'ΰ', + 'ῤ' => 'ῤ', + 'ῥ' => 'ῥ', + 'ῦ' => 'ῦ', + 'ῧ' => 'ῧ', + 'Ῠ' => 'Ῠ', + 'Ῡ' => 'Ῡ', + 'Ὺ' => 'Ὺ', + 'Ύ' => 'Ύ', + 'Ῥ' => 'Ῥ', + '῭' => '῭', + '΅' => '΅', + '`' => '`', + 'ῲ' => 'ῲ', + 'ῳ' => 'ῳ', + 'ῴ' => 'ῴ', + 'ῶ' => 'ῶ', + 'ῷ' => 'ῷ', + 'Ὸ' => 'Ὸ', + 'Ό' => 'Ό', + 'Ὼ' => 'Ὼ', + 'Ώ' => 'Ώ', + 'ῼ' => 'ῼ', + '´' => '´', + ' ' => ' ', + ' ' => ' ', + 'Ω' => 'Ω', + 'K' => 'K', + 'Å' => 'Å', + '↚' => '↚', + '↛' => '↛', + '↮' => '↮', + '⇍' => '⇍', + '⇎' => '⇎', + '⇏' => '⇏', + '∄' => '∄', + '∉' => '∉', + '∌' => '∌', + '∤' => '∤', + '∦' => '∦', + '≁' => '≁', + '≄' => '≄', + '≇' => '≇', + '≉' => '≉', + '≠' => '≠', + '≢' => '≢', + '≭' => '≭', + '≮' => '≮', + '≯' => '≯', + '≰' => '≰', + '≱' => '≱', + '≴' => '≴', + '≵' => '≵', + '≸' => '≸', + '≹' => '≹', + '⊀' => '⊀', + '⊁' => '⊁', + '⊄' => '⊄', + '⊅' => '⊅', + '⊈' => '⊈', + '⊉' => '⊉', + '⊬' => '⊬', + '⊭' => '⊭', + '⊮' => '⊮', + '⊯' => '⊯', + '⋠' => '⋠', + '⋡' => '⋡', + '⋢' => '⋢', + '⋣' => '⋣', + '⋪' => '⋪', + '⋫' => '⋫', + '⋬' => '⋬', + '⋭' => '⋭', + '〈' => '〈', + '〉' => '〉', + '⫝̸' => '⫝̸', + 'が' => 'が', + 'ぎ' => 'ぎ', + 'ぐ' => 'ぐ', + 'げ' => 'げ', + 'ご' => 'ご', + 'ざ' => 'ざ', + 'じ' => 'じ', + 'ず' => 'ず', + 'ぜ' => 'ぜ', + 'ぞ' => 'ぞ', + 'だ' => 'だ', + 'ぢ' => 'ぢ', + 'づ' => 'づ', + 'で' => 'で', + 'ど' => 'ど', + 'ば' => 'ば', + 'ぱ' => 'ぱ', + 'び' => 'び', + 'ぴ' => 'ぴ', + 'ぶ' => 'ぶ', + 'ぷ' => 'ぷ', + 'べ' => 'べ', + 'ぺ' => 'ぺ', + 'ぼ' => 'ぼ', + 'ぽ' => 'ぽ', + 'ゔ' => 'ゔ', + 'ゞ' => 'ゞ', + 'ガ' => 'ガ', + 'ギ' => 'ギ', + 'グ' => 'グ', + 'ゲ' => 'ゲ', + 'ゴ' => 'ゴ', + 'ザ' => 'ザ', + 'ジ' => 'ジ', + 'ズ' => 'ズ', + 'ゼ' => 'ゼ', + 'ゾ' => 'ゾ', + 'ダ' => 'ダ', + 'ヂ' => 'ヂ', + 'ヅ' => 'ヅ', + 'デ' => 'デ', + 'ド' => 'ド', + 'バ' => 'バ', + 'パ' => 'パ', + 'ビ' => 'ビ', + 'ピ' => 'ピ', + 'ブ' => 'ブ', + 'プ' => 'プ', + 'ベ' => 'ベ', + 'ペ' => 'ペ', + 'ボ' => 'ボ', + 'ポ' => 'ポ', + 'ヴ' => 'ヴ', + 'ヷ' => 'ヷ', + 'ヸ' => 'ヸ', + 'ヹ' => 'ヹ', + 'ヺ' => 'ヺ', + 'ヾ' => 'ヾ', + '豈' => '豈', + '更' => '更', + '車' => '車', + '賈' => '賈', + '滑' => '滑', + '串' => '串', + '句' => '句', + '龜' => '龜', + '龜' => '龜', + '契' => '契', + '金' => '金', + '喇' => '喇', + '奈' => '奈', + '懶' => '懶', + '癩' => '癩', + '羅' => '羅', + '蘿' => '蘿', + '螺' => '螺', + '裸' => '裸', + '邏' => '邏', + '樂' => '樂', + '洛' => '洛', + '烙' => '烙', + '珞' => '珞', + '落' => '落', + '酪' => '酪', + '駱' => '駱', + '亂' => '亂', + '卵' => '卵', + '欄' => '欄', + '爛' => '爛', + '蘭' => '蘭', + '鸞' => '鸞', + '嵐' => '嵐', + '濫' => '濫', + '藍' => '藍', + '襤' => '襤', + '拉' => '拉', + '臘' => '臘', + '蠟' => '蠟', + '廊' => '廊', + '朗' => '朗', + '浪' => '浪', + '狼' => '狼', + '郎' => '郎', + '來' => '來', + '冷' => '冷', + '勞' => '勞', + '擄' => '擄', + '櫓' => '櫓', + '爐' => '爐', + '盧' => '盧', + '老' => '老', + '蘆' => '蘆', + '虜' => '虜', + '路' => '路', + '露' => '露', + '魯' => '魯', + '鷺' => '鷺', + '碌' => '碌', + '祿' => '祿', + '綠' => '綠', + '菉' => '菉', + '錄' => '錄', + '鹿' => '鹿', + '論' => '論', + '壟' => '壟', + '弄' => '弄', + '籠' => '籠', + '聾' => '聾', + '牢' => '牢', + '磊' => '磊', + '賂' => '賂', + '雷' => '雷', + '壘' => '壘', + '屢' => '屢', + '樓' => '樓', + '淚' => '淚', + '漏' => '漏', + '累' => '累', + '縷' => '縷', + '陋' => '陋', + '勒' => '勒', + '肋' => '肋', + '凜' => '凜', + '凌' => '凌', + '稜' => '稜', + '綾' => '綾', + '菱' => '菱', + '陵' => '陵', + '讀' => '讀', + '拏' => '拏', + '樂' => '樂', + '諾' => '諾', + '丹' => '丹', + '寧' => '寧', + '怒' => '怒', + '率' => '率', + '異' => '異', + '北' => '北', + '磻' => '磻', + '便' => '便', + '復' => '復', + '不' => '不', + '泌' => '泌', + '數' => '數', + '索' => '索', + '參' => '參', + '塞' => '塞', + '省' => '省', + '葉' => '葉', + '說' => '說', + '殺' => '殺', + '辰' => '辰', + '沈' => '沈', + '拾' => '拾', + '若' => '若', + '掠' => '掠', + '略' => '略', + '亮' => '亮', + '兩' => '兩', + '凉' => '凉', + '梁' => '梁', + '糧' => '糧', + '良' => '良', + '諒' => '諒', + '量' => '量', + '勵' => '勵', + '呂' => '呂', + '女' => '女', + '廬' => '廬', + '旅' => '旅', + '濾' => '濾', + '礪' => '礪', + '閭' => '閭', + '驪' => '驪', + '麗' => '麗', + '黎' => '黎', + '力' => '力', + '曆' => '曆', + '歷' => '歷', + '轢' => '轢', + '年' => '年', + '憐' => '憐', + '戀' => '戀', + '撚' => '撚', + '漣' => '漣', + '煉' => '煉', + '璉' => '璉', + '秊' => '秊', + '練' => '練', + '聯' => '聯', + '輦' => '輦', + '蓮' => '蓮', + '連' => '連', + '鍊' => '鍊', + '列' => '列', + '劣' => '劣', + '咽' => '咽', + '烈' => '烈', + '裂' => '裂', + '說' => '說', + '廉' => '廉', + '念' => '念', + '捻' => '捻', + '殮' => '殮', + '簾' => '簾', + '獵' => '獵', + '令' => '令', + '囹' => '囹', + '寧' => '寧', + '嶺' => '嶺', + '怜' => '怜', + '玲' => '玲', + '瑩' => '瑩', + '羚' => '羚', + '聆' => '聆', + '鈴' => '鈴', + '零' => '零', + '靈' => '靈', + '領' => '領', + '例' => '例', + '禮' => '禮', + '醴' => '醴', + '隸' => '隸', + '惡' => '惡', + '了' => '了', + '僚' => '僚', + '寮' => '寮', + '尿' => '尿', + '料' => '料', + '樂' => '樂', + '燎' => '燎', + '療' => '療', + '蓼' => '蓼', + '遼' => '遼', + '龍' => '龍', + '暈' => '暈', + '阮' => '阮', + '劉' => '劉', + '杻' => '杻', + '柳' => '柳', + '流' => '流', + '溜' => '溜', + '琉' => '琉', + '留' => '留', + '硫' => '硫', + '紐' => '紐', + '類' => '類', + '六' => '六', + '戮' => '戮', + '陸' => '陸', + '倫' => '倫', + '崙' => '崙', + '淪' => '淪', + '輪' => '輪', + '律' => '律', + '慄' => '慄', + '栗' => '栗', + '率' => '率', + '隆' => '隆', + '利' => '利', + '吏' => '吏', + '履' => '履', + '易' => '易', + '李' => '李', + '梨' => '梨', + '泥' => '泥', + '理' => '理', + '痢' => '痢', + '罹' => '罹', + '裏' => '裏', + '裡' => '裡', + '里' => '里', + '離' => '離', + '匿' => '匿', + '溺' => '溺', + '吝' => '吝', + '燐' => '燐', + '璘' => '璘', + '藺' => '藺', + '隣' => '隣', + '鱗' => '鱗', + '麟' => '麟', + '林' => '林', + '淋' => '淋', + '臨' => '臨', + '立' => '立', + '笠' => '笠', + '粒' => '粒', + '狀' => '狀', + '炙' => '炙', + '識' => '識', + '什' => '什', + '茶' => '茶', + '刺' => '刺', + '切' => '切', + '度' => '度', + '拓' => '拓', + '糖' => '糖', + '宅' => '宅', + '洞' => '洞', + '暴' => '暴', + '輻' => '輻', + '行' => '行', + '降' => '降', + '見' => '見', + '廓' => '廓', + '兀' => '兀', + '嗀' => '嗀', + '塚' => '塚', + '晴' => '晴', + '凞' => '凞', + '猪' => '猪', + '益' => '益', + '礼' => '礼', + '神' => '神', + '祥' => '祥', + '福' => '福', + '靖' => '靖', + '精' => '精', + '羽' => '羽', + '蘒' => '蘒', + '諸' => '諸', + '逸' => '逸', + '都' => '都', + '飯' => '飯', + '飼' => '飼', + '館' => '館', + '鶴' => '鶴', + '郞' => '郞', + '隷' => '隷', + '侮' => '侮', + '僧' => '僧', + '免' => '免', + '勉' => '勉', + '勤' => '勤', + '卑' => '卑', + '喝' => '喝', + '嘆' => '嘆', + '器' => '器', + '塀' => '塀', + '墨' => '墨', + '層' => '層', + '屮' => '屮', + '悔' => '悔', + '慨' => '慨', + '憎' => '憎', + '懲' => '懲', + '敏' => '敏', + '既' => '既', + '暑' => '暑', + '梅' => '梅', + '海' => '海', + '渚' => '渚', + '漢' => '漢', + '煮' => '煮', + '爫' => '爫', + '琢' => '琢', + '碑' => '碑', + '社' => '社', + '祉' => '祉', + '祈' => '祈', + '祐' => '祐', + '祖' => '祖', + '祝' => '祝', + '禍' => '禍', + '禎' => '禎', + '穀' => '穀', + '突' => '突', + '節' => '節', + '練' => '練', + '縉' => '縉', + '繁' => '繁', + '署' => '署', + '者' => '者', + '臭' => '臭', + '艹' => '艹', + '艹' => '艹', + '著' => '著', + '褐' => '褐', + '視' => '視', + '謁' => '謁', + '謹' => '謹', + '賓' => '賓', + '贈' => '贈', + '辶' => '辶', + '逸' => '逸', + '難' => '難', + '響' => '響', + '頻' => '頻', + '恵' => '恵', + '𤋮' => '𤋮', + '舘' => '舘', + '並' => '並', + '况' => '况', + '全' => '全', + '侀' => '侀', + '充' => '充', + '冀' => '冀', + '勇' => '勇', + '勺' => '勺', + '喝' => '喝', + '啕' => '啕', + '喙' => '喙', + '嗢' => '嗢', + '塚' => '塚', + '墳' => '墳', + '奄' => '奄', + '奔' => '奔', + '婢' => '婢', + '嬨' => '嬨', + '廒' => '廒', + '廙' => '廙', + '彩' => '彩', + '徭' => '徭', + '惘' => '惘', + '慎' => '慎', + '愈' => '愈', + '憎' => '憎', + '慠' => '慠', + '懲' => '懲', + '戴' => '戴', + '揄' => '揄', + '搜' => '搜', + '摒' => '摒', + '敖' => '敖', + '晴' => '晴', + '朗' => '朗', + '望' => '望', + '杖' => '杖', + '歹' => '歹', + '殺' => '殺', + '流' => '流', + '滛' => '滛', + '滋' => '滋', + '漢' => '漢', + '瀞' => '瀞', + '煮' => '煮', + '瞧' => '瞧', + '爵' => '爵', + '犯' => '犯', + '猪' => '猪', + '瑱' => '瑱', + '甆' => '甆', + '画' => '画', + '瘝' => '瘝', + '瘟' => '瘟', + '益' => '益', + '盛' => '盛', + '直' => '直', + '睊' => '睊', + '着' => '着', + '磌' => '磌', + '窱' => '窱', + '節' => '節', + '类' => '类', + '絛' => '絛', + '練' => '練', + '缾' => '缾', + '者' => '者', + '荒' => '荒', + '華' => '華', + '蝹' => '蝹', + '襁' => '襁', + '覆' => '覆', + '視' => '視', + '調' => '調', + '諸' => '諸', + '請' => '請', + '謁' => '謁', + '諾' => '諾', + '諭' => '諭', + '謹' => '謹', + '變' => '變', + '贈' => '贈', + '輸' => '輸', + '遲' => '遲', + '醙' => '醙', + '鉶' => '鉶', + '陼' => '陼', + '難' => '難', + '靖' => '靖', + '韛' => '韛', + '響' => '響', + '頋' => '頋', + '頻' => '頻', + '鬒' => '鬒', + '龜' => '龜', + '𢡊' => '𢡊', + '𢡄' => '𢡄', + '𣏕' => '𣏕', + '㮝' => '㮝', + '䀘' => '䀘', + '䀹' => '䀹', + '𥉉' => '𥉉', + '𥳐' => '𥳐', + '𧻓' => '𧻓', + '齃' => '齃', + '龎' => '龎', + 'יִ' => 'יִ', + 'ײַ' => 'ײַ', + 'שׁ' => 'שׁ', + 'שׂ' => 'שׂ', + 'שּׁ' => 'שּׁ', + 'שּׂ' => 'שּׂ', + 'אַ' => 'אַ', + 'אָ' => 'אָ', + 'אּ' => 'אּ', + 'בּ' => 'בּ', + 'גּ' => 'גּ', + 'דּ' => 'דּ', + 'הּ' => 'הּ', + 'וּ' => 'וּ', + 'זּ' => 'זּ', + 'טּ' => 'טּ', + 'יּ' => 'יּ', + 'ךּ' => 'ךּ', + 'כּ' => 'כּ', + 'לּ' => 'לּ', + 'מּ' => 'מּ', + 'נּ' => 'נּ', + 'סּ' => 'סּ', + 'ףּ' => 'ףּ', + 'פּ' => 'פּ', + 'צּ' => 'צּ', + 'קּ' => 'קּ', + 'רּ' => 'רּ', + 'שּ' => 'שּ', + 'תּ' => 'תּ', + 'וֹ' => 'וֹ', + 'בֿ' => 'בֿ', + 'כֿ' => 'כֿ', + 'פֿ' => 'פֿ', + '𑂚' => '𑂚', + '𑂜' => '𑂜', + '𑂫' => '𑂫', + '𑄮' => '𑄮', + '𑄯' => '𑄯', + '𑍋' => '𑍋', + '𑍌' => '𑍌', + '𑒻' => '𑒻', + '𑒼' => '𑒼', + '𑒾' => '𑒾', + '𑖺' => '𑖺', + '𑖻' => '𑖻', + '𑤸' => '𑤸', + '𝅗𝅥' => '𝅗𝅥', + '𝅘𝅥' => '𝅘𝅥', + '𝅘𝅥𝅮' => '𝅘𝅥𝅮', + '𝅘𝅥𝅯' => '𝅘𝅥𝅯', + '𝅘𝅥𝅰' => '𝅘𝅥𝅰', + '𝅘𝅥𝅱' => '𝅘𝅥𝅱', + '𝅘𝅥𝅲' => '𝅘𝅥𝅲', + '𝆹𝅥' => '𝆹𝅥', + '𝆺𝅥' => '𝆺𝅥', + '𝆹𝅥𝅮' => '𝆹𝅥𝅮', + '𝆺𝅥𝅮' => '𝆺𝅥𝅮', + '𝆹𝅥𝅯' => '𝆹𝅥𝅯', + '𝆺𝅥𝅯' => '𝆺𝅥𝅯', + '丽' => '丽', + '丸' => '丸', + '乁' => '乁', + '𠄢' => '𠄢', + '你' => '你', + '侮' => '侮', + '侻' => '侻', + '倂' => '倂', + '偺' => '偺', + '備' => '備', + '僧' => '僧', + '像' => '像', + '㒞' => '㒞', + '𠘺' => '𠘺', + '免' => '免', + '兔' => '兔', + '兤' => '兤', + '具' => '具', + '𠔜' => '𠔜', + '㒹' => '㒹', + '內' => '內', + '再' => '再', + '𠕋' => '𠕋', + '冗' => '冗', + '冤' => '冤', + '仌' => '仌', + '冬' => '冬', + '况' => '况', + '𩇟' => '𩇟', + '凵' => '凵', + '刃' => '刃', + '㓟' => '㓟', + '刻' => '刻', + '剆' => '剆', + '割' => '割', + '剷' => '剷', + '㔕' => '㔕', + '勇' => '勇', + '勉' => '勉', + '勤' => '勤', + '勺' => '勺', + '包' => '包', + '匆' => '匆', + '北' => '北', + '卉' => '卉', + '卑' => '卑', + '博' => '博', + '即' => '即', + '卽' => '卽', + '卿' => '卿', + '卿' => '卿', + '卿' => '卿', + '𠨬' => '𠨬', + '灰' => '灰', + '及' => '及', + '叟' => '叟', + '𠭣' => '𠭣', + '叫' => '叫', + '叱' => '叱', + '吆' => '吆', + '咞' => '咞', + '吸' => '吸', + '呈' => '呈', + '周' => '周', + '咢' => '咢', + '哶' => '哶', + '唐' => '唐', + '啓' => '啓', + '啣' => '啣', + '善' => '善', + '善' => '善', + '喙' => '喙', + '喫' => '喫', + '喳' => '喳', + '嗂' => '嗂', + '圖' => '圖', + '嘆' => '嘆', + '圗' => '圗', + '噑' => '噑', + '噴' => '噴', + '切' => '切', + '壮' => '壮', + '城' => '城', + '埴' => '埴', + '堍' => '堍', + '型' => '型', + '堲' => '堲', + '報' => '報', + '墬' => '墬', + '𡓤' => '𡓤', + '売' => '売', + '壷' => '壷', + '夆' => '夆', + '多' => '多', + '夢' => '夢', + '奢' => '奢', + '𡚨' => '𡚨', + '𡛪' => '𡛪', + '姬' => '姬', + '娛' => '娛', + '娧' => '娧', + '姘' => '姘', + '婦' => '婦', + '㛮' => '㛮', + '㛼' => '㛼', + '嬈' => '嬈', + '嬾' => '嬾', + '嬾' => '嬾', + '𡧈' => '𡧈', + '寃' => '寃', + '寘' => '寘', + '寧' => '寧', + '寳' => '寳', + '𡬘' => '𡬘', + '寿' => '寿', + '将' => '将', + '当' => '当', + '尢' => '尢', + '㞁' => '㞁', + '屠' => '屠', + '屮' => '屮', + '峀' => '峀', + '岍' => '岍', + '𡷤' => '𡷤', + '嵃' => '嵃', + '𡷦' => '𡷦', + '嵮' => '嵮', + '嵫' => '嵫', + '嵼' => '嵼', + '巡' => '巡', + '巢' => '巢', + '㠯' => '㠯', + '巽' => '巽', + '帨' => '帨', + '帽' => '帽', + '幩' => '幩', + '㡢' => '㡢', + '𢆃' => '𢆃', + '㡼' => '㡼', + '庰' => '庰', + '庳' => '庳', + '庶' => '庶', + '廊' => '廊', + '𪎒' => '𪎒', + '廾' => '廾', + '𢌱' => '𢌱', + '𢌱' => '𢌱', + '舁' => '舁', + '弢' => '弢', + '弢' => '弢', + '㣇' => '㣇', + '𣊸' => '𣊸', + '𦇚' => '𦇚', + '形' => '形', + '彫' => '彫', + '㣣' => '㣣', + '徚' => '徚', + '忍' => '忍', + '志' => '志', + '忹' => '忹', + '悁' => '悁', + '㤺' => '㤺', + '㤜' => '㤜', + '悔' => '悔', + '𢛔' => '𢛔', + '惇' => '惇', + '慈' => '慈', + '慌' => '慌', + '慎' => '慎', + '慌' => '慌', + '慺' => '慺', + '憎' => '憎', + '憲' => '憲', + '憤' => '憤', + '憯' => '憯', + '懞' => '懞', + '懲' => '懲', + '懶' => '懶', + '成' => '成', + '戛' => '戛', + '扝' => '扝', + '抱' => '抱', + '拔' => '拔', + '捐' => '捐', + '𢬌' => '𢬌', + '挽' => '挽', + '拼' => '拼', + '捨' => '捨', + '掃' => '掃', + '揤' => '揤', + '𢯱' => '𢯱', + '搢' => '搢', + '揅' => '揅', + '掩' => '掩', + '㨮' => '㨮', + '摩' => '摩', + '摾' => '摾', + '撝' => '撝', + '摷' => '摷', + '㩬' => '㩬', + '敏' => '敏', + '敬' => '敬', + '𣀊' => '𣀊', + '旣' => '旣', + '書' => '書', + '晉' => '晉', + '㬙' => '㬙', + '暑' => '暑', + '㬈' => '㬈', + '㫤' => '㫤', + '冒' => '冒', + '冕' => '冕', + '最' => '最', + '暜' => '暜', + '肭' => '肭', + '䏙' => '䏙', + '朗' => '朗', + '望' => '望', + '朡' => '朡', + '杞' => '杞', + '杓' => '杓', + '𣏃' => '𣏃', + '㭉' => '㭉', + '柺' => '柺', + '枅' => '枅', + '桒' => '桒', + '梅' => '梅', + '𣑭' => '𣑭', + '梎' => '梎', + '栟' => '栟', + '椔' => '椔', + '㮝' => '㮝', + '楂' => '楂', + '榣' => '榣', + '槪' => '槪', + '檨' => '檨', + '𣚣' => '𣚣', + '櫛' => '櫛', + '㰘' => '㰘', + '次' => '次', + '𣢧' => '𣢧', + '歔' => '歔', + '㱎' => '㱎', + '歲' => '歲', + '殟' => '殟', + '殺' => '殺', + '殻' => '殻', + '𣪍' => '𣪍', + '𡴋' => '𡴋', + '𣫺' => '𣫺', + '汎' => '汎', + '𣲼' => '𣲼', + '沿' => '沿', + '泍' => '泍', + '汧' => '汧', + '洖' => '洖', + '派' => '派', + '海' => '海', + '流' => '流', + '浩' => '浩', + '浸' => '浸', + '涅' => '涅', + '𣴞' => '𣴞', + '洴' => '洴', + '港' => '港', + '湮' => '湮', + '㴳' => '㴳', + '滋' => '滋', + '滇' => '滇', + '𣻑' => '𣻑', + '淹' => '淹', + '潮' => '潮', + '𣽞' => '𣽞', + '𣾎' => '𣾎', + '濆' => '濆', + '瀹' => '瀹', + '瀞' => '瀞', + '瀛' => '瀛', + '㶖' => '㶖', + '灊' => '灊', + '災' => '災', + '灷' => '灷', + '炭' => '炭', + '𠔥' => '𠔥', + '煅' => '煅', + '𤉣' => '𤉣', + '熜' => '熜', + '𤎫' => '𤎫', + '爨' => '爨', + '爵' => '爵', + '牐' => '牐', + '𤘈' => '𤘈', + '犀' => '犀', + '犕' => '犕', + '𤜵' => '𤜵', + '𤠔' => '𤠔', + '獺' => '獺', + '王' => '王', + '㺬' => '㺬', + '玥' => '玥', + '㺸' => '㺸', + '㺸' => '㺸', + '瑇' => '瑇', + '瑜' => '瑜', + '瑱' => '瑱', + '璅' => '璅', + '瓊' => '瓊', + '㼛' => '㼛', + '甤' => '甤', + '𤰶' => '𤰶', + '甾' => '甾', + '𤲒' => '𤲒', + '異' => '異', + '𢆟' => '𢆟', + '瘐' => '瘐', + '𤾡' => '𤾡', + '𤾸' => '𤾸', + '𥁄' => '𥁄', + '㿼' => '㿼', + '䀈' => '䀈', + '直' => '直', + '𥃳' => '𥃳', + '𥃲' => '𥃲', + '𥄙' => '𥄙', + '𥄳' => '𥄳', + '眞' => '眞', + '真' => '真', + '真' => '真', + '睊' => '睊', + '䀹' => '䀹', + '瞋' => '瞋', + '䁆' => '䁆', + '䂖' => '䂖', + '𥐝' => '𥐝', + '硎' => '硎', + '碌' => '碌', + '磌' => '磌', + '䃣' => '䃣', + '𥘦' => '𥘦', + '祖' => '祖', + '𥚚' => '𥚚', + '𥛅' => '𥛅', + '福' => '福', + '秫' => '秫', + '䄯' => '䄯', + '穀' => '穀', + '穊' => '穊', + '穏' => '穏', + '𥥼' => '𥥼', + '𥪧' => '𥪧', + '𥪧' => '𥪧', + '竮' => '竮', + '䈂' => '䈂', + '𥮫' => '𥮫', + '篆' => '篆', + '築' => '築', + '䈧' => '䈧', + '𥲀' => '𥲀', + '糒' => '糒', + '䊠' => '䊠', + '糨' => '糨', + '糣' => '糣', + '紀' => '紀', + '𥾆' => '𥾆', + '絣' => '絣', + '䌁' => '䌁', + '緇' => '緇', + '縂' => '縂', + '繅' => '繅', + '䌴' => '䌴', + '𦈨' => '𦈨', + '𦉇' => '𦉇', + '䍙' => '䍙', + '𦋙' => '𦋙', + '罺' => '罺', + '𦌾' => '𦌾', + '羕' => '羕', + '翺' => '翺', + '者' => '者', + '𦓚' => '𦓚', + '𦔣' => '𦔣', + '聠' => '聠', + '𦖨' => '𦖨', + '聰' => '聰', + '𣍟' => '𣍟', + '䏕' => '䏕', + '育' => '育', + '脃' => '脃', + '䐋' => '䐋', + '脾' => '脾', + '媵' => '媵', + '𦞧' => '𦞧', + '𦞵' => '𦞵', + '𣎓' => '𣎓', + '𣎜' => '𣎜', + '舁' => '舁', + '舄' => '舄', + '辞' => '辞', + '䑫' => '䑫', + '芑' => '芑', + '芋' => '芋', + '芝' => '芝', + '劳' => '劳', + '花' => '花', + '芳' => '芳', + '芽' => '芽', + '苦' => '苦', + '𦬼' => '𦬼', + '若' => '若', + '茝' => '茝', + '荣' => '荣', + '莭' => '莭', + '茣' => '茣', + '莽' => '莽', + '菧' => '菧', + '著' => '著', + '荓' => '荓', + '菊' => '菊', + '菌' => '菌', + '菜' => '菜', + '𦰶' => '𦰶', + '𦵫' => '𦵫', + '𦳕' => '𦳕', + '䔫' => '䔫', + '蓱' => '蓱', + '蓳' => '蓳', + '蔖' => '蔖', + '𧏊' => '𧏊', + '蕤' => '蕤', + '𦼬' => '𦼬', + '䕝' => '䕝', + '䕡' => '䕡', + '𦾱' => '𦾱', + '𧃒' => '𧃒', + '䕫' => '䕫', + '虐' => '虐', + '虜' => '虜', + '虧' => '虧', + '虩' => '虩', + '蚩' => '蚩', + '蚈' => '蚈', + '蜎' => '蜎', + '蛢' => '蛢', + '蝹' => '蝹', + '蜨' => '蜨', + '蝫' => '蝫', + '螆' => '螆', + '䗗' => '䗗', + '蟡' => '蟡', + '蠁' => '蠁', + '䗹' => '䗹', + '衠' => '衠', + '衣' => '衣', + '𧙧' => '𧙧', + '裗' => '裗', + '裞' => '裞', + '䘵' => '䘵', + '裺' => '裺', + '㒻' => '㒻', + '𧢮' => '𧢮', + '𧥦' => '𧥦', + '䚾' => '䚾', + '䛇' => '䛇', + '誠' => '誠', + '諭' => '諭', + '變' => '變', + '豕' => '豕', + '𧲨' => '𧲨', + '貫' => '貫', + '賁' => '賁', + '贛' => '贛', + '起' => '起', + '𧼯' => '𧼯', + '𠠄' => '𠠄', + '跋' => '跋', + '趼' => '趼', + '跰' => '跰', + '𠣞' => '𠣞', + '軔' => '軔', + '輸' => '輸', + '𨗒' => '𨗒', + '𨗭' => '𨗭', + '邔' => '邔', + '郱' => '郱', + '鄑' => '鄑', + '𨜮' => '𨜮', + '鄛' => '鄛', + '鈸' => '鈸', + '鋗' => '鋗', + '鋘' => '鋘', + '鉼' => '鉼', + '鏹' => '鏹', + '鐕' => '鐕', + '𨯺' => '𨯺', + '開' => '開', + '䦕' => '䦕', + '閷' => '閷', + '𨵷' => '𨵷', + '䧦' => '䧦', + '雃' => '雃', + '嶲' => '嶲', + '霣' => '霣', + '𩅅' => '𩅅', + '𩈚' => '𩈚', + '䩮' => '䩮', + '䩶' => '䩶', + '韠' => '韠', + '𩐊' => '𩐊', + '䪲' => '䪲', + '𩒖' => '𩒖', + '頋' => '頋', + '頋' => '頋', + '頩' => '頩', + '𩖶' => '𩖶', + '飢' => '飢', + '䬳' => '䬳', + '餩' => '餩', + '馧' => '馧', + '駂' => '駂', + '駾' => '駾', + '䯎' => '䯎', + '𩬰' => '𩬰', + '鬒' => '鬒', + '鱀' => '鱀', + '鳽' => '鳽', + '䳎' => '䳎', + '䳭' => '䳭', + '鵧' => '鵧', + '𪃎' => '𪃎', + '䳸' => '䳸', + '𪄅' => '𪄅', + '𪈎' => '𪈎', + '𪊑' => '𪊑', + '麻' => '麻', + '䵖' => '䵖', + '黹' => '黹', + '黾' => '黾', + '鼅' => '鼅', + '鼏' => '鼏', + '鼖' => '鼖', + '鼻' => '鼻', + '𪘀' => '𪘀', +); diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php new file mode 100644 index 0000000..ec90f36 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php @@ -0,0 +1,876 @@ + 230, + '́' => 230, + '̂' => 230, + '̃' => 230, + '̄' => 230, + '̅' => 230, + '̆' => 230, + '̇' => 230, + '̈' => 230, + '̉' => 230, + '̊' => 230, + '̋' => 230, + '̌' => 230, + '̍' => 230, + '̎' => 230, + '̏' => 230, + '̐' => 230, + '̑' => 230, + '̒' => 230, + '̓' => 230, + '̔' => 230, + '̕' => 232, + '̖' => 220, + '̗' => 220, + '̘' => 220, + '̙' => 220, + '̚' => 232, + '̛' => 216, + '̜' => 220, + '̝' => 220, + '̞' => 220, + '̟' => 220, + '̠' => 220, + '̡' => 202, + '̢' => 202, + '̣' => 220, + '̤' => 220, + '̥' => 220, + '̦' => 220, + '̧' => 202, + '̨' => 202, + '̩' => 220, + '̪' => 220, + '̫' => 220, + '̬' => 220, + '̭' => 220, + '̮' => 220, + '̯' => 220, + '̰' => 220, + '̱' => 220, + '̲' => 220, + '̳' => 220, + '̴' => 1, + '̵' => 1, + '̶' => 1, + '̷' => 1, + '̸' => 1, + '̹' => 220, + '̺' => 220, + '̻' => 220, + '̼' => 220, + '̽' => 230, + '̾' => 230, + '̿' => 230, + '̀' => 230, + '́' => 230, + '͂' => 230, + '̓' => 230, + '̈́' => 230, + 'ͅ' => 240, + '͆' => 230, + '͇' => 220, + '͈' => 220, + '͉' => 220, + '͊' => 230, + '͋' => 230, + '͌' => 230, + '͍' => 220, + '͎' => 220, + '͐' => 230, + '͑' => 230, + '͒' => 230, + '͓' => 220, + '͔' => 220, + '͕' => 220, + '͖' => 220, + '͗' => 230, + '͘' => 232, + '͙' => 220, + '͚' => 220, + '͛' => 230, + '͜' => 233, + '͝' => 234, + '͞' => 234, + '͟' => 233, + '͠' => 234, + '͡' => 234, + '͢' => 233, + 'ͣ' => 230, + 'ͤ' => 230, + 'ͥ' => 230, + 'ͦ' => 230, + 'ͧ' => 230, + 'ͨ' => 230, + 'ͩ' => 230, + 'ͪ' => 230, + 'ͫ' => 230, + 'ͬ' => 230, + 'ͭ' => 230, + 'ͮ' => 230, + 'ͯ' => 230, + '҃' => 230, + '҄' => 230, + '҅' => 230, + '҆' => 230, + '҇' => 230, + '֑' => 220, + '֒' => 230, + '֓' => 230, + '֔' => 230, + '֕' => 230, + '֖' => 220, + '֗' => 230, + '֘' => 230, + '֙' => 230, + '֚' => 222, + '֛' => 220, + '֜' => 230, + '֝' => 230, + '֞' => 230, + '֟' => 230, + '֠' => 230, + '֡' => 230, + '֢' => 220, + '֣' => 220, + '֤' => 220, + '֥' => 220, + '֦' => 220, + '֧' => 220, + '֨' => 230, + '֩' => 230, + '֪' => 220, + '֫' => 230, + '֬' => 230, + '֭' => 222, + '֮' => 228, + '֯' => 230, + 'ְ' => 10, + 'ֱ' => 11, + 'ֲ' => 12, + 'ֳ' => 13, + 'ִ' => 14, + 'ֵ' => 15, + 'ֶ' => 16, + 'ַ' => 17, + 'ָ' => 18, + 'ֹ' => 19, + 'ֺ' => 19, + 'ֻ' => 20, + 'ּ' => 21, + 'ֽ' => 22, + 'ֿ' => 23, + 'ׁ' => 24, + 'ׂ' => 25, + 'ׄ' => 230, + 'ׅ' => 220, + 'ׇ' => 18, + 'ؐ' => 230, + 'ؑ' => 230, + 'ؒ' => 230, + 'ؓ' => 230, + 'ؔ' => 230, + 'ؕ' => 230, + 'ؖ' => 230, + 'ؗ' => 230, + 'ؘ' => 30, + 'ؙ' => 31, + 'ؚ' => 32, + 'ً' => 27, + 'ٌ' => 28, + 'ٍ' => 29, + 'َ' => 30, + 'ُ' => 31, + 'ِ' => 32, + 'ّ' => 33, + 'ْ' => 34, + 'ٓ' => 230, + 'ٔ' => 230, + 'ٕ' => 220, + 'ٖ' => 220, + 'ٗ' => 230, + '٘' => 230, + 'ٙ' => 230, + 'ٚ' => 230, + 'ٛ' => 230, + 'ٜ' => 220, + 'ٝ' => 230, + 'ٞ' => 230, + 'ٟ' => 220, + 'ٰ' => 35, + 'ۖ' => 230, + 'ۗ' => 230, + 'ۘ' => 230, + 'ۙ' => 230, + 'ۚ' => 230, + 'ۛ' => 230, + 'ۜ' => 230, + '۟' => 230, + '۠' => 230, + 'ۡ' => 230, + 'ۢ' => 230, + 'ۣ' => 220, + 'ۤ' => 230, + 'ۧ' => 230, + 'ۨ' => 230, + '۪' => 220, + '۫' => 230, + '۬' => 230, + 'ۭ' => 220, + 'ܑ' => 36, + 'ܰ' => 230, + 'ܱ' => 220, + 'ܲ' => 230, + 'ܳ' => 230, + 'ܴ' => 220, + 'ܵ' => 230, + 'ܶ' => 230, + 'ܷ' => 220, + 'ܸ' => 220, + 'ܹ' => 220, + 'ܺ' => 230, + 'ܻ' => 220, + 'ܼ' => 220, + 'ܽ' => 230, + 'ܾ' => 220, + 'ܿ' => 230, + '݀' => 230, + '݁' => 230, + '݂' => 220, + '݃' => 230, + '݄' => 220, + '݅' => 230, + '݆' => 220, + '݇' => 230, + '݈' => 220, + '݉' => 230, + '݊' => 230, + '߫' => 230, + '߬' => 230, + '߭' => 230, + '߮' => 230, + '߯' => 230, + '߰' => 230, + '߱' => 230, + '߲' => 220, + '߳' => 230, + '߽' => 220, + 'ࠖ' => 230, + 'ࠗ' => 230, + '࠘' => 230, + '࠙' => 230, + 'ࠛ' => 230, + 'ࠜ' => 230, + 'ࠝ' => 230, + 'ࠞ' => 230, + 'ࠟ' => 230, + 'ࠠ' => 230, + 'ࠡ' => 230, + 'ࠢ' => 230, + 'ࠣ' => 230, + 'ࠥ' => 230, + 'ࠦ' => 230, + 'ࠧ' => 230, + 'ࠩ' => 230, + 'ࠪ' => 230, + 'ࠫ' => 230, + 'ࠬ' => 230, + '࠭' => 230, + '࡙' => 220, + '࡚' => 220, + '࡛' => 220, + '࣓' => 220, + 'ࣔ' => 230, + 'ࣕ' => 230, + 'ࣖ' => 230, + 'ࣗ' => 230, + 'ࣘ' => 230, + 'ࣙ' => 230, + 'ࣚ' => 230, + 'ࣛ' => 230, + 'ࣜ' => 230, + 'ࣝ' => 230, + 'ࣞ' => 230, + 'ࣟ' => 230, + '࣠' => 230, + '࣡' => 230, + 'ࣣ' => 220, + 'ࣤ' => 230, + 'ࣥ' => 230, + 'ࣦ' => 220, + 'ࣧ' => 230, + 'ࣨ' => 230, + 'ࣩ' => 220, + '࣪' => 230, + '࣫' => 230, + '࣬' => 230, + '࣭' => 220, + '࣮' => 220, + '࣯' => 220, + 'ࣰ' => 27, + 'ࣱ' => 28, + 'ࣲ' => 29, + 'ࣳ' => 230, + 'ࣴ' => 230, + 'ࣵ' => 230, + 'ࣶ' => 220, + 'ࣷ' => 230, + 'ࣸ' => 230, + 'ࣹ' => 220, + 'ࣺ' => 220, + 'ࣻ' => 230, + 'ࣼ' => 230, + 'ࣽ' => 230, + 'ࣾ' => 230, + 'ࣿ' => 230, + '़' => 7, + '्' => 9, + '॑' => 230, + '॒' => 220, + '॓' => 230, + '॔' => 230, + '়' => 7, + '্' => 9, + '৾' => 230, + '਼' => 7, + '੍' => 9, + '઼' => 7, + '્' => 9, + '଼' => 7, + '୍' => 9, + '்' => 9, + '్' => 9, + 'ౕ' => 84, + 'ౖ' => 91, + '಼' => 7, + '್' => 9, + '഻' => 9, + '഼' => 9, + '്' => 9, + '්' => 9, + 'ุ' => 103, + 'ู' => 103, + 'ฺ' => 9, + '่' => 107, + '้' => 107, + '๊' => 107, + '๋' => 107, + 'ຸ' => 118, + 'ູ' => 118, + '຺' => 9, + '່' => 122, + '້' => 122, + '໊' => 122, + '໋' => 122, + '༘' => 220, + '༙' => 220, + '༵' => 220, + '༷' => 220, + '༹' => 216, + 'ཱ' => 129, + 'ི' => 130, + 'ུ' => 132, + 'ེ' => 130, + 'ཻ' => 130, + 'ོ' => 130, + 'ཽ' => 130, + 'ྀ' => 130, + 'ྂ' => 230, + 'ྃ' => 230, + '྄' => 9, + '྆' => 230, + '྇' => 230, + '࿆' => 220, + '့' => 7, + '္' => 9, + '်' => 9, + 'ႍ' => 220, + '፝' => 230, + '፞' => 230, + '፟' => 230, + '᜔' => 9, + '᜴' => 9, + '្' => 9, + '៝' => 230, + 'ᢩ' => 228, + '᤹' => 222, + '᤺' => 230, + '᤻' => 220, + 'ᨗ' => 230, + 'ᨘ' => 220, + '᩠' => 9, + '᩵' => 230, + '᩶' => 230, + '᩷' => 230, + '᩸' => 230, + '᩹' => 230, + '᩺' => 230, + '᩻' => 230, + '᩼' => 230, + '᩿' => 220, + '᪰' => 230, + '᪱' => 230, + '᪲' => 230, + '᪳' => 230, + '᪴' => 230, + '᪵' => 220, + '᪶' => 220, + '᪷' => 220, + '᪸' => 220, + '᪹' => 220, + '᪺' => 220, + '᪻' => 230, + '᪼' => 230, + '᪽' => 220, + 'ᪿ' => 220, + 'ᫀ' => 220, + '᬴' => 7, + '᭄' => 9, + '᭫' => 230, + '᭬' => 220, + '᭭' => 230, + '᭮' => 230, + '᭯' => 230, + '᭰' => 230, + '᭱' => 230, + '᭲' => 230, + '᭳' => 230, + '᮪' => 9, + '᮫' => 9, + '᯦' => 7, + '᯲' => 9, + '᯳' => 9, + '᰷' => 7, + '᳐' => 230, + '᳑' => 230, + '᳒' => 230, + '᳔' => 1, + '᳕' => 220, + '᳖' => 220, + '᳗' => 220, + '᳘' => 220, + '᳙' => 220, + '᳚' => 230, + '᳛' => 230, + '᳜' => 220, + '᳝' => 220, + '᳞' => 220, + '᳟' => 220, + '᳠' => 230, + '᳢' => 1, + '᳣' => 1, + '᳤' => 1, + '᳥' => 1, + '᳦' => 1, + '᳧' => 1, + '᳨' => 1, + '᳭' => 220, + '᳴' => 230, + '᳸' => 230, + '᳹' => 230, + '᷀' => 230, + '᷁' => 230, + '᷂' => 220, + '᷃' => 230, + '᷄' => 230, + '᷅' => 230, + '᷆' => 230, + '᷇' => 230, + '᷈' => 230, + '᷉' => 230, + '᷊' => 220, + '᷋' => 230, + '᷌' => 230, + '᷍' => 234, + '᷎' => 214, + '᷏' => 220, + '᷐' => 202, + '᷑' => 230, + '᷒' => 230, + 'ᷓ' => 230, + 'ᷔ' => 230, + 'ᷕ' => 230, + 'ᷖ' => 230, + 'ᷗ' => 230, + 'ᷘ' => 230, + 'ᷙ' => 230, + 'ᷚ' => 230, + 'ᷛ' => 230, + 'ᷜ' => 230, + 'ᷝ' => 230, + 'ᷞ' => 230, + 'ᷟ' => 230, + 'ᷠ' => 230, + 'ᷡ' => 230, + 'ᷢ' => 230, + 'ᷣ' => 230, + 'ᷤ' => 230, + 'ᷥ' => 230, + 'ᷦ' => 230, + 'ᷧ' => 230, + 'ᷨ' => 230, + 'ᷩ' => 230, + 'ᷪ' => 230, + 'ᷫ' => 230, + 'ᷬ' => 230, + 'ᷭ' => 230, + 'ᷮ' => 230, + 'ᷯ' => 230, + 'ᷰ' => 230, + 'ᷱ' => 230, + 'ᷲ' => 230, + 'ᷳ' => 230, + 'ᷴ' => 230, + '᷵' => 230, + '᷶' => 232, + '᷷' => 228, + '᷸' => 228, + '᷹' => 220, + '᷻' => 230, + '᷼' => 233, + '᷽' => 220, + '᷾' => 230, + '᷿' => 220, + '⃐' => 230, + '⃑' => 230, + '⃒' => 1, + '⃓' => 1, + '⃔' => 230, + '⃕' => 230, + '⃖' => 230, + '⃗' => 230, + '⃘' => 1, + '⃙' => 1, + '⃚' => 1, + '⃛' => 230, + '⃜' => 230, + '⃡' => 230, + '⃥' => 1, + '⃦' => 1, + '⃧' => 230, + '⃨' => 220, + '⃩' => 230, + '⃪' => 1, + '⃫' => 1, + '⃬' => 220, + '⃭' => 220, + '⃮' => 220, + '⃯' => 220, + '⃰' => 230, + '⳯' => 230, + '⳰' => 230, + '⳱' => 230, + '⵿' => 9, + 'ⷠ' => 230, + 'ⷡ' => 230, + 'ⷢ' => 230, + 'ⷣ' => 230, + 'ⷤ' => 230, + 'ⷥ' => 230, + 'ⷦ' => 230, + 'ⷧ' => 230, + 'ⷨ' => 230, + 'ⷩ' => 230, + 'ⷪ' => 230, + 'ⷫ' => 230, + 'ⷬ' => 230, + 'ⷭ' => 230, + 'ⷮ' => 230, + 'ⷯ' => 230, + 'ⷰ' => 230, + 'ⷱ' => 230, + 'ⷲ' => 230, + 'ⷳ' => 230, + 'ⷴ' => 230, + 'ⷵ' => 230, + 'ⷶ' => 230, + 'ⷷ' => 230, + 'ⷸ' => 230, + 'ⷹ' => 230, + 'ⷺ' => 230, + 'ⷻ' => 230, + 'ⷼ' => 230, + 'ⷽ' => 230, + 'ⷾ' => 230, + 'ⷿ' => 230, + '〪' => 218, + '〫' => 228, + '〬' => 232, + '〭' => 222, + '〮' => 224, + '〯' => 224, + '゙' => 8, + '゚' => 8, + '꙯' => 230, + 'ꙴ' => 230, + 'ꙵ' => 230, + 'ꙶ' => 230, + 'ꙷ' => 230, + 'ꙸ' => 230, + 'ꙹ' => 230, + 'ꙺ' => 230, + 'ꙻ' => 230, + '꙼' => 230, + '꙽' => 230, + 'ꚞ' => 230, + 'ꚟ' => 230, + '꛰' => 230, + '꛱' => 230, + '꠆' => 9, + '꠬' => 9, + '꣄' => 9, + '꣠' => 230, + '꣡' => 230, + '꣢' => 230, + '꣣' => 230, + '꣤' => 230, + '꣥' => 230, + '꣦' => 230, + '꣧' => 230, + '꣨' => 230, + '꣩' => 230, + '꣪' => 230, + '꣫' => 230, + '꣬' => 230, + '꣭' => 230, + '꣮' => 230, + '꣯' => 230, + '꣰' => 230, + '꣱' => 230, + '꤫' => 220, + '꤬' => 220, + '꤭' => 220, + '꥓' => 9, + '꦳' => 7, + '꧀' => 9, + 'ꪰ' => 230, + 'ꪲ' => 230, + 'ꪳ' => 230, + 'ꪴ' => 220, + 'ꪷ' => 230, + 'ꪸ' => 230, + 'ꪾ' => 230, + '꪿' => 230, + '꫁' => 230, + '꫶' => 9, + '꯭' => 9, + 'ﬞ' => 26, + '︠' => 230, + '︡' => 230, + '︢' => 230, + '︣' => 230, + '︤' => 230, + '︥' => 230, + '︦' => 230, + '︧' => 220, + '︨' => 220, + '︩' => 220, + '︪' => 220, + '︫' => 220, + '︬' => 220, + '︭' => 220, + '︮' => 230, + '︯' => 230, + '𐇽' => 220, + '𐋠' => 220, + '𐍶' => 230, + '𐍷' => 230, + '𐍸' => 230, + '𐍹' => 230, + '𐍺' => 230, + '𐨍' => 220, + '𐨏' => 230, + '𐨸' => 230, + '𐨹' => 1, + '𐨺' => 220, + '𐨿' => 9, + '𐫥' => 230, + '𐫦' => 220, + '𐴤' => 230, + '𐴥' => 230, + '𐴦' => 230, + '𐴧' => 230, + '𐺫' => 230, + '𐺬' => 230, + '𐽆' => 220, + '𐽇' => 220, + '𐽈' => 230, + '𐽉' => 230, + '𐽊' => 230, + '𐽋' => 220, + '𐽌' => 230, + '𐽍' => 220, + '𐽎' => 220, + '𐽏' => 220, + '𐽐' => 220, + '𑁆' => 9, + '𑁿' => 9, + '𑂹' => 9, + '𑂺' => 7, + '𑄀' => 230, + '𑄁' => 230, + '𑄂' => 230, + '𑄳' => 9, + '𑄴' => 9, + '𑅳' => 7, + '𑇀' => 9, + '𑇊' => 7, + '𑈵' => 9, + '𑈶' => 7, + '𑋩' => 7, + '𑋪' => 9, + '𑌻' => 7, + '𑌼' => 7, + '𑍍' => 9, + '𑍦' => 230, + '𑍧' => 230, + '𑍨' => 230, + '𑍩' => 230, + '𑍪' => 230, + '𑍫' => 230, + '𑍬' => 230, + '𑍰' => 230, + '𑍱' => 230, + '𑍲' => 230, + '𑍳' => 230, + '𑍴' => 230, + '𑑂' => 9, + '𑑆' => 7, + '𑑞' => 230, + '𑓂' => 9, + '𑓃' => 7, + '𑖿' => 9, + '𑗀' => 7, + '𑘿' => 9, + '𑚶' => 9, + '𑚷' => 7, + '𑜫' => 9, + '𑠹' => 9, + '𑠺' => 7, + '𑤽' => 9, + '𑤾' => 9, + '𑥃' => 7, + '𑧠' => 9, + '𑨴' => 9, + '𑩇' => 9, + '𑪙' => 9, + '𑰿' => 9, + '𑵂' => 7, + '𑵄' => 9, + '𑵅' => 9, + '𑶗' => 9, + '𖫰' => 1, + '𖫱' => 1, + '𖫲' => 1, + '𖫳' => 1, + '𖫴' => 1, + '𖬰' => 230, + '𖬱' => 230, + '𖬲' => 230, + '𖬳' => 230, + '𖬴' => 230, + '𖬵' => 230, + '𖬶' => 230, + '𖿰' => 6, + '𖿱' => 6, + '𛲞' => 1, + '𝅥' => 216, + '𝅦' => 216, + '𝅧' => 1, + '𝅨' => 1, + '𝅩' => 1, + '𝅭' => 226, + '𝅮' => 216, + '𝅯' => 216, + '𝅰' => 216, + '𝅱' => 216, + '𝅲' => 216, + '𝅻' => 220, + '𝅼' => 220, + '𝅽' => 220, + '𝅾' => 220, + '𝅿' => 220, + '𝆀' => 220, + '𝆁' => 220, + '𝆂' => 220, + '𝆅' => 230, + '𝆆' => 230, + '𝆇' => 230, + '𝆈' => 230, + '𝆉' => 230, + '𝆊' => 220, + '𝆋' => 220, + '𝆪' => 230, + '𝆫' => 230, + '𝆬' => 230, + '𝆭' => 230, + '𝉂' => 230, + '𝉃' => 230, + '𝉄' => 230, + '𞀀' => 230, + '𞀁' => 230, + '𞀂' => 230, + '𞀃' => 230, + '𞀄' => 230, + '𞀅' => 230, + '𞀆' => 230, + '𞀈' => 230, + '𞀉' => 230, + '𞀊' => 230, + '𞀋' => 230, + '𞀌' => 230, + '𞀍' => 230, + '𞀎' => 230, + '𞀏' => 230, + '𞀐' => 230, + '𞀑' => 230, + '𞀒' => 230, + '𞀓' => 230, + '𞀔' => 230, + '𞀕' => 230, + '𞀖' => 230, + '𞀗' => 230, + '𞀘' => 230, + '𞀛' => 230, + '𞀜' => 230, + '𞀝' => 230, + '𞀞' => 230, + '𞀟' => 230, + '𞀠' => 230, + '𞀡' => 230, + '𞀣' => 230, + '𞀤' => 230, + '𞀦' => 230, + '𞀧' => 230, + '𞀨' => 230, + '𞀩' => 230, + '𞀪' => 230, + '𞄰' => 230, + '𞄱' => 230, + '𞄲' => 230, + '𞄳' => 230, + '𞄴' => 230, + '𞄵' => 230, + '𞄶' => 230, + '𞋬' => 230, + '𞋭' => 230, + '𞋮' => 230, + '𞋯' => 230, + '𞣐' => 220, + '𞣑' => 220, + '𞣒' => 220, + '𞣓' => 220, + '𞣔' => 220, + '𞣕' => 220, + '𞣖' => 220, + '𞥄' => 230, + '𞥅' => 230, + '𞥆' => 230, + '𞥇' => 230, + '𞥈' => 230, + '𞥉' => 230, + '𞥊' => 7, +); diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php new file mode 100644 index 0000000..1574902 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php @@ -0,0 +1,3695 @@ + ' ', + '¨' => ' ̈', + 'ª' => 'a', + '¯' => ' ̄', + '²' => '2', + '³' => '3', + '´' => ' ́', + 'µ' => 'μ', + '¸' => ' ̧', + '¹' => '1', + 'º' => 'o', + '¼' => '1⁄4', + '½' => '1⁄2', + '¾' => '3⁄4', + 'IJ' => 'IJ', + 'ij' => 'ij', + 'Ŀ' => 'L·', + 'ŀ' => 'l·', + 'ʼn' => 'ʼn', + 'ſ' => 's', + 'DŽ' => 'DŽ', + 'Dž' => 'Dž', + 'dž' => 'dž', + 'LJ' => 'LJ', + 'Lj' => 'Lj', + 'lj' => 'lj', + 'NJ' => 'NJ', + 'Nj' => 'Nj', + 'nj' => 'nj', + 'DZ' => 'DZ', + 'Dz' => 'Dz', + 'dz' => 'dz', + 'ʰ' => 'h', + 'ʱ' => 'ɦ', + 'ʲ' => 'j', + 'ʳ' => 'r', + 'ʴ' => 'ɹ', + 'ʵ' => 'ɻ', + 'ʶ' => 'ʁ', + 'ʷ' => 'w', + 'ʸ' => 'y', + '˘' => ' ̆', + '˙' => ' ̇', + '˚' => ' ̊', + '˛' => ' ̨', + '˜' => ' ̃', + '˝' => ' ̋', + 'ˠ' => 'ɣ', + 'ˡ' => 'l', + 'ˢ' => 's', + 'ˣ' => 'x', + 'ˤ' => 'ʕ', + 'ͺ' => ' ͅ', + '΄' => ' ́', + '΅' => ' ̈́', + 'ϐ' => 'β', + 'ϑ' => 'θ', + 'ϒ' => 'Υ', + 'ϓ' => 'Ύ', + 'ϔ' => 'Ϋ', + 'ϕ' => 'φ', + 'ϖ' => 'π', + 'ϰ' => 'κ', + 'ϱ' => 'ρ', + 'ϲ' => 'ς', + 'ϴ' => 'Θ', + 'ϵ' => 'ε', + 'Ϲ' => 'Σ', + 'և' => 'եւ', + 'ٵ' => 'اٴ', + 'ٶ' => 'وٴ', + 'ٷ' => 'ۇٴ', + 'ٸ' => 'يٴ', + 'ำ' => 'ํา', + 'ຳ' => 'ໍາ', + 'ໜ' => 'ຫນ', + 'ໝ' => 'ຫມ', + '༌' => '་', + 'ཷ' => 'ྲཱྀ', + 'ཹ' => 'ླཱྀ', + 'ჼ' => 'ნ', + 'ᴬ' => 'A', + 'ᴭ' => 'Æ', + 'ᴮ' => 'B', + 'ᴰ' => 'D', + 'ᴱ' => 'E', + 'ᴲ' => 'Ǝ', + 'ᴳ' => 'G', + 'ᴴ' => 'H', + 'ᴵ' => 'I', + 'ᴶ' => 'J', + 'ᴷ' => 'K', + 'ᴸ' => 'L', + 'ᴹ' => 'M', + 'ᴺ' => 'N', + 'ᴼ' => 'O', + 'ᴽ' => 'Ȣ', + 'ᴾ' => 'P', + 'ᴿ' => 'R', + 'ᵀ' => 'T', + 'ᵁ' => 'U', + 'ᵂ' => 'W', + 'ᵃ' => 'a', + 'ᵄ' => 'ɐ', + 'ᵅ' => 'ɑ', + 'ᵆ' => 'ᴂ', + 'ᵇ' => 'b', + 'ᵈ' => 'd', + 'ᵉ' => 'e', + 'ᵊ' => 'ə', + 'ᵋ' => 'ɛ', + 'ᵌ' => 'ɜ', + 'ᵍ' => 'g', + 'ᵏ' => 'k', + 'ᵐ' => 'm', + 'ᵑ' => 'ŋ', + 'ᵒ' => 'o', + 'ᵓ' => 'ɔ', + 'ᵔ' => 'ᴖ', + 'ᵕ' => 'ᴗ', + 'ᵖ' => 'p', + 'ᵗ' => 't', + 'ᵘ' => 'u', + 'ᵙ' => 'ᴝ', + 'ᵚ' => 'ɯ', + 'ᵛ' => 'v', + 'ᵜ' => 'ᴥ', + 'ᵝ' => 'β', + 'ᵞ' => 'γ', + 'ᵟ' => 'δ', + 'ᵠ' => 'φ', + 'ᵡ' => 'χ', + 'ᵢ' => 'i', + 'ᵣ' => 'r', + 'ᵤ' => 'u', + 'ᵥ' => 'v', + 'ᵦ' => 'β', + 'ᵧ' => 'γ', + 'ᵨ' => 'ρ', + 'ᵩ' => 'φ', + 'ᵪ' => 'χ', + 'ᵸ' => 'н', + 'ᶛ' => 'ɒ', + 'ᶜ' => 'c', + 'ᶝ' => 'ɕ', + 'ᶞ' => 'ð', + 'ᶟ' => 'ɜ', + 'ᶠ' => 'f', + 'ᶡ' => 'ɟ', + 'ᶢ' => 'ɡ', + 'ᶣ' => 'ɥ', + 'ᶤ' => 'ɨ', + 'ᶥ' => 'ɩ', + 'ᶦ' => 'ɪ', + 'ᶧ' => 'ᵻ', + 'ᶨ' => 'ʝ', + 'ᶩ' => 'ɭ', + 'ᶪ' => 'ᶅ', + 'ᶫ' => 'ʟ', + 'ᶬ' => 'ɱ', + 'ᶭ' => 'ɰ', + 'ᶮ' => 'ɲ', + 'ᶯ' => 'ɳ', + 'ᶰ' => 'ɴ', + 'ᶱ' => 'ɵ', + 'ᶲ' => 'ɸ', + 'ᶳ' => 'ʂ', + 'ᶴ' => 'ʃ', + 'ᶵ' => 'ƫ', + 'ᶶ' => 'ʉ', + 'ᶷ' => 'ʊ', + 'ᶸ' => 'ᴜ', + 'ᶹ' => 'ʋ', + 'ᶺ' => 'ʌ', + 'ᶻ' => 'z', + 'ᶼ' => 'ʐ', + 'ᶽ' => 'ʑ', + 'ᶾ' => 'ʒ', + 'ᶿ' => 'θ', + 'ẚ' => 'aʾ', + 'ẛ' => 'ṡ', + '᾽' => ' ̓', + '᾿' => ' ̓', + '῀' => ' ͂', + '῁' => ' ̈͂', + '῍' => ' ̓̀', + '῎' => ' ̓́', + '῏' => ' ̓͂', + '῝' => ' ̔̀', + '῞' => ' ̔́', + '῟' => ' ̔͂', + '῭' => ' ̈̀', + '΅' => ' ̈́', + '´' => ' ́', + '῾' => ' ̔', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + '‑' => '‐', + '‗' => ' ̳', + '․' => '.', + '‥' => '..', + '…' => '...', + ' ' => ' ', + '″' => '′′', + '‴' => '′′′', + '‶' => '‵‵', + '‷' => '‵‵‵', + '‼' => '!!', + '‾' => ' ̅', + '⁇' => '??', + '⁈' => '?!', + '⁉' => '!?', + '⁗' => '′′′′', + ' ' => ' ', + '⁰' => '0', + 'ⁱ' => 'i', + '⁴' => '4', + '⁵' => '5', + '⁶' => '6', + '⁷' => '7', + '⁸' => '8', + '⁹' => '9', + '⁺' => '+', + '⁻' => '−', + '⁼' => '=', + '⁽' => '(', + '⁾' => ')', + 'ⁿ' => 'n', + '₀' => '0', + '₁' => '1', + '₂' => '2', + '₃' => '3', + '₄' => '4', + '₅' => '5', + '₆' => '6', + '₇' => '7', + '₈' => '8', + '₉' => '9', + '₊' => '+', + '₋' => '−', + '₌' => '=', + '₍' => '(', + '₎' => ')', + 'ₐ' => 'a', + 'ₑ' => 'e', + 'ₒ' => 'o', + 'ₓ' => 'x', + 'ₔ' => 'ə', + 'ₕ' => 'h', + 'ₖ' => 'k', + 'ₗ' => 'l', + 'ₘ' => 'm', + 'ₙ' => 'n', + 'ₚ' => 'p', + 'ₛ' => 's', + 'ₜ' => 't', + '₨' => 'Rs', + '℀' => 'a/c', + '℁' => 'a/s', + 'ℂ' => 'C', + '℃' => '°C', + '℅' => 'c/o', + '℆' => 'c/u', + 'ℇ' => 'Ɛ', + '℉' => '°F', + 'ℊ' => 'g', + 'ℋ' => 'H', + 'ℌ' => 'H', + 'ℍ' => 'H', + 'ℎ' => 'h', + 'ℏ' => 'ħ', + 'ℐ' => 'I', + 'ℑ' => 'I', + 'ℒ' => 'L', + 'ℓ' => 'l', + 'ℕ' => 'N', + '№' => 'No', + 'ℙ' => 'P', + 'ℚ' => 'Q', + 'ℛ' => 'R', + 'ℜ' => 'R', + 'ℝ' => 'R', + '℠' => 'SM', + '℡' => 'TEL', + '™' => 'TM', + 'ℤ' => 'Z', + 'ℨ' => 'Z', + 'ℬ' => 'B', + 'ℭ' => 'C', + 'ℯ' => 'e', + 'ℰ' => 'E', + 'ℱ' => 'F', + 'ℳ' => 'M', + 'ℴ' => 'o', + 'ℵ' => 'א', + 'ℶ' => 'ב', + 'ℷ' => 'ג', + 'ℸ' => 'ד', + 'ℹ' => 'i', + '℻' => 'FAX', + 'ℼ' => 'π', + 'ℽ' => 'γ', + 'ℾ' => 'Γ', + 'ℿ' => 'Π', + '⅀' => '∑', + 'ⅅ' => 'D', + 'ⅆ' => 'd', + 'ⅇ' => 'e', + 'ⅈ' => 'i', + 'ⅉ' => 'j', + '⅐' => '1⁄7', + '⅑' => '1⁄9', + '⅒' => '1⁄10', + '⅓' => '1⁄3', + '⅔' => '2⁄3', + '⅕' => '1⁄5', + '⅖' => '2⁄5', + '⅗' => '3⁄5', + '⅘' => '4⁄5', + '⅙' => '1⁄6', + '⅚' => '5⁄6', + '⅛' => '1⁄8', + '⅜' => '3⁄8', + '⅝' => '5⁄8', + '⅞' => '7⁄8', + '⅟' => '1⁄', + 'Ⅰ' => 'I', + 'Ⅱ' => 'II', + 'Ⅲ' => 'III', + 'Ⅳ' => 'IV', + 'Ⅴ' => 'V', + 'Ⅵ' => 'VI', + 'Ⅶ' => 'VII', + 'Ⅷ' => 'VIII', + 'Ⅸ' => 'IX', + 'Ⅹ' => 'X', + 'Ⅺ' => 'XI', + 'Ⅻ' => 'XII', + 'Ⅼ' => 'L', + 'Ⅽ' => 'C', + 'Ⅾ' => 'D', + 'Ⅿ' => 'M', + 'ⅰ' => 'i', + 'ⅱ' => 'ii', + 'ⅲ' => 'iii', + 'ⅳ' => 'iv', + 'ⅴ' => 'v', + 'ⅵ' => 'vi', + 'ⅶ' => 'vii', + 'ⅷ' => 'viii', + 'ⅸ' => 'ix', + 'ⅹ' => 'x', + 'ⅺ' => 'xi', + 'ⅻ' => 'xii', + 'ⅼ' => 'l', + 'ⅽ' => 'c', + 'ⅾ' => 'd', + 'ⅿ' => 'm', + '↉' => '0⁄3', + '∬' => '∫∫', + '∭' => '∫∫∫', + '∯' => '∮∮', + '∰' => '∮∮∮', + '①' => '1', + '②' => '2', + '③' => '3', + '④' => '4', + '⑤' => '5', + '⑥' => '6', + '⑦' => '7', + '⑧' => '8', + '⑨' => '9', + '⑩' => '10', + '⑪' => '11', + '⑫' => '12', + '⑬' => '13', + '⑭' => '14', + '⑮' => '15', + '⑯' => '16', + '⑰' => '17', + '⑱' => '18', + '⑲' => '19', + '⑳' => '20', + '⑴' => '(1)', + '⑵' => '(2)', + '⑶' => '(3)', + '⑷' => '(4)', + '⑸' => '(5)', + '⑹' => '(6)', + '⑺' => '(7)', + '⑻' => '(8)', + '⑼' => '(9)', + '⑽' => '(10)', + '⑾' => '(11)', + '⑿' => '(12)', + '⒀' => '(13)', + '⒁' => '(14)', + '⒂' => '(15)', + '⒃' => '(16)', + '⒄' => '(17)', + '⒅' => '(18)', + '⒆' => '(19)', + '⒇' => '(20)', + '⒈' => '1.', + '⒉' => '2.', + '⒊' => '3.', + '⒋' => '4.', + '⒌' => '5.', + '⒍' => '6.', + '⒎' => '7.', + '⒏' => '8.', + '⒐' => '9.', + '⒑' => '10.', + '⒒' => '11.', + '⒓' => '12.', + '⒔' => '13.', + '⒕' => '14.', + '⒖' => '15.', + '⒗' => '16.', + '⒘' => '17.', + '⒙' => '18.', + '⒚' => '19.', + '⒛' => '20.', + '⒜' => '(a)', + '⒝' => '(b)', + '⒞' => '(c)', + '⒟' => '(d)', + '⒠' => '(e)', + '⒡' => '(f)', + '⒢' => '(g)', + '⒣' => '(h)', + '⒤' => '(i)', + '⒥' => '(j)', + '⒦' => '(k)', + '⒧' => '(l)', + '⒨' => '(m)', + '⒩' => '(n)', + '⒪' => '(o)', + '⒫' => '(p)', + '⒬' => '(q)', + '⒭' => '(r)', + '⒮' => '(s)', + '⒯' => '(t)', + '⒰' => '(u)', + '⒱' => '(v)', + '⒲' => '(w)', + '⒳' => '(x)', + '⒴' => '(y)', + '⒵' => '(z)', + 'Ⓐ' => 'A', + 'Ⓑ' => 'B', + 'Ⓒ' => 'C', + 'Ⓓ' => 'D', + 'Ⓔ' => 'E', + 'Ⓕ' => 'F', + 'Ⓖ' => 'G', + 'Ⓗ' => 'H', + 'Ⓘ' => 'I', + 'Ⓙ' => 'J', + 'Ⓚ' => 'K', + 'Ⓛ' => 'L', + 'Ⓜ' => 'M', + 'Ⓝ' => 'N', + 'Ⓞ' => 'O', + 'Ⓟ' => 'P', + 'Ⓠ' => 'Q', + 'Ⓡ' => 'R', + 'Ⓢ' => 'S', + 'Ⓣ' => 'T', + 'Ⓤ' => 'U', + 'Ⓥ' => 'V', + 'Ⓦ' => 'W', + 'Ⓧ' => 'X', + 'Ⓨ' => 'Y', + 'Ⓩ' => 'Z', + 'ⓐ' => 'a', + 'ⓑ' => 'b', + 'ⓒ' => 'c', + 'ⓓ' => 'd', + 'ⓔ' => 'e', + 'ⓕ' => 'f', + 'ⓖ' => 'g', + 'ⓗ' => 'h', + 'ⓘ' => 'i', + 'ⓙ' => 'j', + 'ⓚ' => 'k', + 'ⓛ' => 'l', + 'ⓜ' => 'm', + 'ⓝ' => 'n', + 'ⓞ' => 'o', + 'ⓟ' => 'p', + 'ⓠ' => 'q', + 'ⓡ' => 'r', + 'ⓢ' => 's', + 'ⓣ' => 't', + 'ⓤ' => 'u', + 'ⓥ' => 'v', + 'ⓦ' => 'w', + 'ⓧ' => 'x', + 'ⓨ' => 'y', + 'ⓩ' => 'z', + '⓪' => '0', + '⨌' => '∫∫∫∫', + '⩴' => '::=', + '⩵' => '==', + '⩶' => '===', + 'ⱼ' => 'j', + 'ⱽ' => 'V', + 'ⵯ' => 'ⵡ', + '⺟' => '母', + '⻳' => '龟', + '⼀' => '一', + '⼁' => '丨', + '⼂' => '丶', + '⼃' => '丿', + '⼄' => '乙', + '⼅' => '亅', + '⼆' => '二', + '⼇' => '亠', + '⼈' => '人', + '⼉' => '儿', + '⼊' => '入', + '⼋' => '八', + '⼌' => '冂', + '⼍' => '冖', + '⼎' => '冫', + '⼏' => '几', + '⼐' => '凵', + '⼑' => '刀', + '⼒' => '力', + '⼓' => '勹', + '⼔' => '匕', + '⼕' => '匚', + '⼖' => '匸', + '⼗' => '十', + '⼘' => '卜', + '⼙' => '卩', + '⼚' => '厂', + '⼛' => '厶', + '⼜' => '又', + '⼝' => '口', + '⼞' => '囗', + '⼟' => '土', + '⼠' => '士', + '⼡' => '夂', + '⼢' => '夊', + '⼣' => '夕', + '⼤' => '大', + '⼥' => '女', + '⼦' => '子', + '⼧' => '宀', + '⼨' => '寸', + '⼩' => '小', + '⼪' => '尢', + '⼫' => '尸', + '⼬' => '屮', + '⼭' => '山', + '⼮' => '巛', + '⼯' => '工', + '⼰' => '己', + '⼱' => '巾', + '⼲' => '干', + '⼳' => '幺', + '⼴' => '广', + '⼵' => '廴', + '⼶' => '廾', + '⼷' => '弋', + '⼸' => '弓', + '⼹' => '彐', + '⼺' => '彡', + '⼻' => '彳', + '⼼' => '心', + '⼽' => '戈', + '⼾' => '戶', + '⼿' => '手', + '⽀' => '支', + '⽁' => '攴', + '⽂' => '文', + '⽃' => '斗', + '⽄' => '斤', + '⽅' => '方', + '⽆' => '无', + '⽇' => '日', + '⽈' => '曰', + '⽉' => '月', + '⽊' => '木', + '⽋' => '欠', + '⽌' => '止', + '⽍' => '歹', + '⽎' => '殳', + '⽏' => '毋', + '⽐' => '比', + '⽑' => '毛', + '⽒' => '氏', + '⽓' => '气', + '⽔' => '水', + '⽕' => '火', + '⽖' => '爪', + '⽗' => '父', + '⽘' => '爻', + '⽙' => '爿', + '⽚' => '片', + '⽛' => '牙', + '⽜' => '牛', + '⽝' => '犬', + '⽞' => '玄', + '⽟' => '玉', + '⽠' => '瓜', + '⽡' => '瓦', + '⽢' => '甘', + '⽣' => '生', + '⽤' => '用', + '⽥' => '田', + '⽦' => '疋', + '⽧' => '疒', + '⽨' => '癶', + '⽩' => '白', + '⽪' => '皮', + '⽫' => '皿', + '⽬' => '目', + '⽭' => '矛', + '⽮' => '矢', + '⽯' => '石', + '⽰' => '示', + '⽱' => '禸', + '⽲' => '禾', + '⽳' => '穴', + '⽴' => '立', + '⽵' => '竹', + '⽶' => '米', + '⽷' => '糸', + '⽸' => '缶', + '⽹' => '网', + '⽺' => '羊', + '⽻' => '羽', + '⽼' => '老', + '⽽' => '而', + '⽾' => '耒', + '⽿' => '耳', + '⾀' => '聿', + '⾁' => '肉', + '⾂' => '臣', + '⾃' => '自', + '⾄' => '至', + '⾅' => '臼', + '⾆' => '舌', + '⾇' => '舛', + '⾈' => '舟', + '⾉' => '艮', + '⾊' => '色', + '⾋' => '艸', + '⾌' => '虍', + '⾍' => '虫', + '⾎' => '血', + '⾏' => '行', + '⾐' => '衣', + '⾑' => '襾', + '⾒' => '見', + '⾓' => '角', + '⾔' => '言', + '⾕' => '谷', + '⾖' => '豆', + '⾗' => '豕', + '⾘' => '豸', + '⾙' => '貝', + '⾚' => '赤', + '⾛' => '走', + '⾜' => '足', + '⾝' => '身', + '⾞' => '車', + '⾟' => '辛', + '⾠' => '辰', + '⾡' => '辵', + '⾢' => '邑', + '⾣' => '酉', + '⾤' => '釆', + '⾥' => '里', + '⾦' => '金', + '⾧' => '長', + '⾨' => '門', + '⾩' => '阜', + '⾪' => '隶', + '⾫' => '隹', + '⾬' => '雨', + '⾭' => '靑', + '⾮' => '非', + '⾯' => '面', + '⾰' => '革', + '⾱' => '韋', + '⾲' => '韭', + '⾳' => '音', + '⾴' => '頁', + '⾵' => '風', + '⾶' => '飛', + '⾷' => '食', + '⾸' => '首', + '⾹' => '香', + '⾺' => '馬', + '⾻' => '骨', + '⾼' => '高', + '⾽' => '髟', + '⾾' => '鬥', + '⾿' => '鬯', + '⿀' => '鬲', + '⿁' => '鬼', + '⿂' => '魚', + '⿃' => '鳥', + '⿄' => '鹵', + '⿅' => '鹿', + '⿆' => '麥', + '⿇' => '麻', + '⿈' => '黃', + '⿉' => '黍', + '⿊' => '黑', + '⿋' => '黹', + '⿌' => '黽', + '⿍' => '鼎', + '⿎' => '鼓', + '⿏' => '鼠', + '⿐' => '鼻', + '⿑' => '齊', + '⿒' => '齒', + '⿓' => '龍', + '⿔' => '龜', + '⿕' => '龠', + ' ' => ' ', + '〶' => '〒', + '〸' => '十', + '〹' => '卄', + '〺' => '卅', + '゛' => ' ゙', + '゜' => ' ゚', + 'ゟ' => 'より', + 'ヿ' => 'コト', + 'ㄱ' => 'ᄀ', + 'ㄲ' => 'ᄁ', + 'ㄳ' => 'ᆪ', + 'ㄴ' => 'ᄂ', + 'ㄵ' => 'ᆬ', + 'ㄶ' => 'ᆭ', + 'ㄷ' => 'ᄃ', + 'ㄸ' => 'ᄄ', + 'ㄹ' => 'ᄅ', + 'ㄺ' => 'ᆰ', + 'ㄻ' => 'ᆱ', + 'ㄼ' => 'ᆲ', + 'ㄽ' => 'ᆳ', + 'ㄾ' => 'ᆴ', + 'ㄿ' => 'ᆵ', + 'ㅀ' => 'ᄚ', + 'ㅁ' => 'ᄆ', + 'ㅂ' => 'ᄇ', + 'ㅃ' => 'ᄈ', + 'ㅄ' => 'ᄡ', + 'ㅅ' => 'ᄉ', + 'ㅆ' => 'ᄊ', + 'ㅇ' => 'ᄋ', + 'ㅈ' => 'ᄌ', + 'ㅉ' => 'ᄍ', + 'ㅊ' => 'ᄎ', + 'ㅋ' => 'ᄏ', + 'ㅌ' => 'ᄐ', + 'ㅍ' => 'ᄑ', + 'ㅎ' => 'ᄒ', + 'ㅏ' => 'ᅡ', + 'ㅐ' => 'ᅢ', + 'ㅑ' => 'ᅣ', + 'ㅒ' => 'ᅤ', + 'ㅓ' => 'ᅥ', + 'ㅔ' => 'ᅦ', + 'ㅕ' => 'ᅧ', + 'ㅖ' => 'ᅨ', + 'ㅗ' => 'ᅩ', + 'ㅘ' => 'ᅪ', + 'ㅙ' => 'ᅫ', + 'ㅚ' => 'ᅬ', + 'ㅛ' => 'ᅭ', + 'ㅜ' => 'ᅮ', + 'ㅝ' => 'ᅯ', + 'ㅞ' => 'ᅰ', + 'ㅟ' => 'ᅱ', + 'ㅠ' => 'ᅲ', + 'ㅡ' => 'ᅳ', + 'ㅢ' => 'ᅴ', + 'ㅣ' => 'ᅵ', + 'ㅤ' => 'ᅠ', + 'ㅥ' => 'ᄔ', + 'ㅦ' => 'ᄕ', + 'ㅧ' => 'ᇇ', + 'ㅨ' => 'ᇈ', + 'ㅩ' => 'ᇌ', + 'ㅪ' => 'ᇎ', + 'ㅫ' => 'ᇓ', + 'ㅬ' => 'ᇗ', + 'ㅭ' => 'ᇙ', + 'ㅮ' => 'ᄜ', + 'ㅯ' => 'ᇝ', + 'ㅰ' => 'ᇟ', + 'ㅱ' => 'ᄝ', + 'ㅲ' => 'ᄞ', + 'ㅳ' => 'ᄠ', + 'ㅴ' => 'ᄢ', + 'ㅵ' => 'ᄣ', + 'ㅶ' => 'ᄧ', + 'ㅷ' => 'ᄩ', + 'ㅸ' => 'ᄫ', + 'ㅹ' => 'ᄬ', + 'ㅺ' => 'ᄭ', + 'ㅻ' => 'ᄮ', + 'ㅼ' => 'ᄯ', + 'ㅽ' => 'ᄲ', + 'ㅾ' => 'ᄶ', + 'ㅿ' => 'ᅀ', + 'ㆀ' => 'ᅇ', + 'ㆁ' => 'ᅌ', + 'ㆂ' => 'ᇱ', + 'ㆃ' => 'ᇲ', + 'ㆄ' => 'ᅗ', + 'ㆅ' => 'ᅘ', + 'ㆆ' => 'ᅙ', + 'ㆇ' => 'ᆄ', + 'ㆈ' => 'ᆅ', + 'ㆉ' => 'ᆈ', + 'ㆊ' => 'ᆑ', + 'ㆋ' => 'ᆒ', + 'ㆌ' => 'ᆔ', + 'ㆍ' => 'ᆞ', + 'ㆎ' => 'ᆡ', + '㆒' => '一', + '㆓' => '二', + '㆔' => '三', + '㆕' => '四', + '㆖' => '上', + '㆗' => '中', + '㆘' => '下', + '㆙' => '甲', + '㆚' => '乙', + '㆛' => '丙', + '㆜' => '丁', + '㆝' => '天', + '㆞' => '地', + '㆟' => '人', + '㈀' => '(ᄀ)', + '㈁' => '(ᄂ)', + '㈂' => '(ᄃ)', + '㈃' => '(ᄅ)', + '㈄' => '(ᄆ)', + '㈅' => '(ᄇ)', + '㈆' => '(ᄉ)', + '㈇' => '(ᄋ)', + '㈈' => '(ᄌ)', + '㈉' => '(ᄎ)', + '㈊' => '(ᄏ)', + '㈋' => '(ᄐ)', + '㈌' => '(ᄑ)', + '㈍' => '(ᄒ)', + '㈎' => '(가)', + '㈏' => '(나)', + '㈐' => '(다)', + '㈑' => '(라)', + '㈒' => '(마)', + '㈓' => '(바)', + '㈔' => '(사)', + '㈕' => '(아)', + '㈖' => '(자)', + '㈗' => '(차)', + '㈘' => '(카)', + '㈙' => '(타)', + '㈚' => '(파)', + '㈛' => '(하)', + '㈜' => '(주)', + '㈝' => '(오전)', + '㈞' => '(오후)', + '㈠' => '(一)', + '㈡' => '(二)', + '㈢' => '(三)', + '㈣' => '(四)', + '㈤' => '(五)', + '㈥' => '(六)', + '㈦' => '(七)', + '㈧' => '(八)', + '㈨' => '(九)', + '㈩' => '(十)', + '㈪' => '(月)', + '㈫' => '(火)', + '㈬' => '(水)', + '㈭' => '(木)', + '㈮' => '(金)', + '㈯' => '(土)', + '㈰' => '(日)', + '㈱' => '(株)', + '㈲' => '(有)', + '㈳' => '(社)', + '㈴' => '(名)', + '㈵' => '(特)', + '㈶' => '(財)', + '㈷' => '(祝)', + '㈸' => '(労)', + '㈹' => '(代)', + '㈺' => '(呼)', + '㈻' => '(学)', + '㈼' => '(監)', + '㈽' => '(企)', + '㈾' => '(資)', + '㈿' => '(協)', + '㉀' => '(祭)', + '㉁' => '(休)', + '㉂' => '(自)', + '㉃' => '(至)', + '㉄' => '問', + '㉅' => '幼', + '㉆' => '文', + '㉇' => '箏', + '㉐' => 'PTE', + '㉑' => '21', + '㉒' => '22', + '㉓' => '23', + '㉔' => '24', + '㉕' => '25', + '㉖' => '26', + '㉗' => '27', + '㉘' => '28', + '㉙' => '29', + '㉚' => '30', + '㉛' => '31', + '㉜' => '32', + '㉝' => '33', + '㉞' => '34', + '㉟' => '35', + '㉠' => 'ᄀ', + '㉡' => 'ᄂ', + '㉢' => 'ᄃ', + '㉣' => 'ᄅ', + '㉤' => 'ᄆ', + '㉥' => 'ᄇ', + '㉦' => 'ᄉ', + '㉧' => 'ᄋ', + '㉨' => 'ᄌ', + '㉩' => 'ᄎ', + '㉪' => 'ᄏ', + '㉫' => 'ᄐ', + '㉬' => 'ᄑ', + '㉭' => 'ᄒ', + '㉮' => '가', + '㉯' => '나', + '㉰' => '다', + '㉱' => '라', + '㉲' => '마', + '㉳' => '바', + '㉴' => '사', + '㉵' => '아', + '㉶' => '자', + '㉷' => '차', + '㉸' => '카', + '㉹' => '타', + '㉺' => '파', + '㉻' => '하', + '㉼' => '참고', + '㉽' => '주의', + '㉾' => '우', + '㊀' => '一', + '㊁' => '二', + '㊂' => '三', + '㊃' => '四', + '㊄' => '五', + '㊅' => '六', + '㊆' => '七', + '㊇' => '八', + '㊈' => '九', + '㊉' => '十', + '㊊' => '月', + '㊋' => '火', + '㊌' => '水', + '㊍' => '木', + '㊎' => '金', + '㊏' => '土', + '㊐' => '日', + '㊑' => '株', + '㊒' => '有', + '㊓' => '社', + '㊔' => '名', + '㊕' => '特', + '㊖' => '財', + '㊗' => '祝', + '㊘' => '労', + '㊙' => '秘', + '㊚' => '男', + '㊛' => '女', + '㊜' => '適', + '㊝' => '優', + '㊞' => '印', + '㊟' => '注', + '㊠' => '項', + '㊡' => '休', + '㊢' => '写', + '㊣' => '正', + '㊤' => '上', + '㊥' => '中', + '㊦' => '下', + '㊧' => '左', + '㊨' => '右', + '㊩' => '医', + '㊪' => '宗', + '㊫' => '学', + '㊬' => '監', + '㊭' => '企', + '㊮' => '資', + '㊯' => '協', + '㊰' => '夜', + '㊱' => '36', + '㊲' => '37', + '㊳' => '38', + '㊴' => '39', + '㊵' => '40', + '㊶' => '41', + '㊷' => '42', + '㊸' => '43', + '㊹' => '44', + '㊺' => '45', + '㊻' => '46', + '㊼' => '47', + '㊽' => '48', + '㊾' => '49', + '㊿' => '50', + '㋀' => '1月', + '㋁' => '2月', + '㋂' => '3月', + '㋃' => '4月', + '㋄' => '5月', + '㋅' => '6月', + '㋆' => '7月', + '㋇' => '8月', + '㋈' => '9月', + '㋉' => '10月', + '㋊' => '11月', + '㋋' => '12月', + '㋌' => 'Hg', + '㋍' => 'erg', + '㋎' => 'eV', + '㋏' => 'LTD', + '㋐' => 'ア', + '㋑' => 'イ', + '㋒' => 'ウ', + '㋓' => 'エ', + '㋔' => 'オ', + '㋕' => 'カ', + '㋖' => 'キ', + '㋗' => 'ク', + '㋘' => 'ケ', + '㋙' => 'コ', + '㋚' => 'サ', + '㋛' => 'シ', + '㋜' => 'ス', + '㋝' => 'セ', + '㋞' => 'ソ', + '㋟' => 'タ', + '㋠' => 'チ', + '㋡' => 'ツ', + '㋢' => 'テ', + '㋣' => 'ト', + '㋤' => 'ナ', + '㋥' => 'ニ', + '㋦' => 'ヌ', + '㋧' => 'ネ', + '㋨' => 'ノ', + '㋩' => 'ハ', + '㋪' => 'ヒ', + '㋫' => 'フ', + '㋬' => 'ヘ', + '㋭' => 'ホ', + '㋮' => 'マ', + '㋯' => 'ミ', + '㋰' => 'ム', + '㋱' => 'メ', + '㋲' => 'モ', + '㋳' => 'ヤ', + '㋴' => 'ユ', + '㋵' => 'ヨ', + '㋶' => 'ラ', + '㋷' => 'リ', + '㋸' => 'ル', + '㋹' => 'レ', + '㋺' => 'ロ', + '㋻' => 'ワ', + '㋼' => 'ヰ', + '㋽' => 'ヱ', + '㋾' => 'ヲ', + '㋿' => '令和', + '㌀' => 'アパート', + '㌁' => 'アルファ', + '㌂' => 'アンペア', + '㌃' => 'アール', + '㌄' => 'イニング', + '㌅' => 'インチ', + '㌆' => 'ウォン', + '㌇' => 'エスクード', + '㌈' => 'エーカー', + '㌉' => 'オンス', + '㌊' => 'オーム', + '㌋' => 'カイリ', + '㌌' => 'カラット', + '㌍' => 'カロリー', + '㌎' => 'ガロン', + '㌏' => 'ガンマ', + '㌐' => 'ギガ', + '㌑' => 'ギニー', + '㌒' => 'キュリー', + '㌓' => 'ギルダー', + '㌔' => 'キロ', + '㌕' => 'キログラム', + '㌖' => 'キロメートル', + '㌗' => 'キロワット', + '㌘' => 'グラム', + '㌙' => 'グラムトン', + '㌚' => 'クルゼイロ', + '㌛' => 'クローネ', + '㌜' => 'ケース', + '㌝' => 'コルナ', + '㌞' => 'コーポ', + '㌟' => 'サイクル', + '㌠' => 'サンチーム', + '㌡' => 'シリング', + '㌢' => 'センチ', + '㌣' => 'セント', + '㌤' => 'ダース', + '㌥' => 'デシ', + '㌦' => 'ドル', + '㌧' => 'トン', + '㌨' => 'ナノ', + '㌩' => 'ノット', + '㌪' => 'ハイツ', + '㌫' => 'パーセント', + '㌬' => 'パーツ', + '㌭' => 'バーレル', + '㌮' => 'ピアストル', + '㌯' => 'ピクル', + '㌰' => 'ピコ', + '㌱' => 'ビル', + '㌲' => 'ファラッド', + '㌳' => 'フィート', + '㌴' => 'ブッシェル', + '㌵' => 'フラン', + '㌶' => 'ヘクタール', + '㌷' => 'ペソ', + '㌸' => 'ペニヒ', + '㌹' => 'ヘルツ', + '㌺' => 'ペンス', + '㌻' => 'ページ', + '㌼' => 'ベータ', + '㌽' => 'ポイント', + '㌾' => 'ボルト', + '㌿' => 'ホン', + '㍀' => 'ポンド', + '㍁' => 'ホール', + '㍂' => 'ホーン', + '㍃' => 'マイクロ', + '㍄' => 'マイル', + '㍅' => 'マッハ', + '㍆' => 'マルク', + '㍇' => 'マンション', + '㍈' => 'ミクロン', + '㍉' => 'ミリ', + '㍊' => 'ミリバール', + '㍋' => 'メガ', + '㍌' => 'メガトン', + '㍍' => 'メートル', + '㍎' => 'ヤード', + '㍏' => 'ヤール', + '㍐' => 'ユアン', + '㍑' => 'リットル', + '㍒' => 'リラ', + '㍓' => 'ルピー', + '㍔' => 'ルーブル', + '㍕' => 'レム', + '㍖' => 'レントゲン', + '㍗' => 'ワット', + '㍘' => '0点', + '㍙' => '1点', + '㍚' => '2点', + '㍛' => '3点', + '㍜' => '4点', + '㍝' => '5点', + '㍞' => '6点', + '㍟' => '7点', + '㍠' => '8点', + '㍡' => '9点', + '㍢' => '10点', + '㍣' => '11点', + '㍤' => '12点', + '㍥' => '13点', + '㍦' => '14点', + '㍧' => '15点', + '㍨' => '16点', + '㍩' => '17点', + '㍪' => '18点', + '㍫' => '19点', + '㍬' => '20点', + '㍭' => '21点', + '㍮' => '22点', + '㍯' => '23点', + '㍰' => '24点', + '㍱' => 'hPa', + '㍲' => 'da', + '㍳' => 'AU', + '㍴' => 'bar', + '㍵' => 'oV', + '㍶' => 'pc', + '㍷' => 'dm', + '㍸' => 'dm2', + '㍹' => 'dm3', + '㍺' => 'IU', + '㍻' => '平成', + '㍼' => '昭和', + '㍽' => '大正', + '㍾' => '明治', + '㍿' => '株式会社', + '㎀' => 'pA', + '㎁' => 'nA', + '㎂' => 'μA', + '㎃' => 'mA', + '㎄' => 'kA', + '㎅' => 'KB', + '㎆' => 'MB', + '㎇' => 'GB', + '㎈' => 'cal', + '㎉' => 'kcal', + '㎊' => 'pF', + '㎋' => 'nF', + '㎌' => 'μF', + '㎍' => 'μg', + '㎎' => 'mg', + '㎏' => 'kg', + '㎐' => 'Hz', + '㎑' => 'kHz', + '㎒' => 'MHz', + '㎓' => 'GHz', + '㎔' => 'THz', + '㎕' => 'μl', + '㎖' => 'ml', + '㎗' => 'dl', + '㎘' => 'kl', + '㎙' => 'fm', + '㎚' => 'nm', + '㎛' => 'μm', + '㎜' => 'mm', + '㎝' => 'cm', + '㎞' => 'km', + '㎟' => 'mm2', + '㎠' => 'cm2', + '㎡' => 'm2', + '㎢' => 'km2', + '㎣' => 'mm3', + '㎤' => 'cm3', + '㎥' => 'm3', + '㎦' => 'km3', + '㎧' => 'm∕s', + '㎨' => 'm∕s2', + '㎩' => 'Pa', + '㎪' => 'kPa', + '㎫' => 'MPa', + '㎬' => 'GPa', + '㎭' => 'rad', + '㎮' => 'rad∕s', + '㎯' => 'rad∕s2', + '㎰' => 'ps', + '㎱' => 'ns', + '㎲' => 'μs', + '㎳' => 'ms', + '㎴' => 'pV', + '㎵' => 'nV', + '㎶' => 'μV', + '㎷' => 'mV', + '㎸' => 'kV', + '㎹' => 'MV', + '㎺' => 'pW', + '㎻' => 'nW', + '㎼' => 'μW', + '㎽' => 'mW', + '㎾' => 'kW', + '㎿' => 'MW', + '㏀' => 'kΩ', + '㏁' => 'MΩ', + '㏂' => 'a.m.', + '㏃' => 'Bq', + '㏄' => 'cc', + '㏅' => 'cd', + '㏆' => 'C∕kg', + '㏇' => 'Co.', + '㏈' => 'dB', + '㏉' => 'Gy', + '㏊' => 'ha', + '㏋' => 'HP', + '㏌' => 'in', + '㏍' => 'KK', + '㏎' => 'KM', + '㏏' => 'kt', + '㏐' => 'lm', + '㏑' => 'ln', + '㏒' => 'log', + '㏓' => 'lx', + '㏔' => 'mb', + '㏕' => 'mil', + '㏖' => 'mol', + '㏗' => 'PH', + '㏘' => 'p.m.', + '㏙' => 'PPM', + '㏚' => 'PR', + '㏛' => 'sr', + '㏜' => 'Sv', + '㏝' => 'Wb', + '㏞' => 'V∕m', + '㏟' => 'A∕m', + '㏠' => '1日', + '㏡' => '2日', + '㏢' => '3日', + '㏣' => '4日', + '㏤' => '5日', + '㏥' => '6日', + '㏦' => '7日', + '㏧' => '8日', + '㏨' => '9日', + '㏩' => '10日', + '㏪' => '11日', + '㏫' => '12日', + '㏬' => '13日', + '㏭' => '14日', + '㏮' => '15日', + '㏯' => '16日', + '㏰' => '17日', + '㏱' => '18日', + '㏲' => '19日', + '㏳' => '20日', + '㏴' => '21日', + '㏵' => '22日', + '㏶' => '23日', + '㏷' => '24日', + '㏸' => '25日', + '㏹' => '26日', + '㏺' => '27日', + '㏻' => '28日', + '㏼' => '29日', + '㏽' => '30日', + '㏾' => '31日', + '㏿' => 'gal', + 'ꚜ' => 'ъ', + 'ꚝ' => 'ь', + 'ꝰ' => 'ꝯ', + 'ꟸ' => 'Ħ', + 'ꟹ' => 'œ', + 'ꭜ' => 'ꜧ', + 'ꭝ' => 'ꬷ', + 'ꭞ' => 'ɫ', + 'ꭟ' => 'ꭒ', + 'ꭩ' => 'ʍ', + 'ff' => 'ff', + 'fi' => 'fi', + 'fl' => 'fl', + 'ffi' => 'ffi', + 'ffl' => 'ffl', + 'ſt' => 'st', + 'st' => 'st', + 'ﬓ' => 'մն', + 'ﬔ' => 'մե', + 'ﬕ' => 'մի', + 'ﬖ' => 'վն', + 'ﬗ' => 'մխ', + 'ﬠ' => 'ע', + 'ﬡ' => 'א', + 'ﬢ' => 'ד', + 'ﬣ' => 'ה', + 'ﬤ' => 'כ', + 'ﬥ' => 'ל', + 'ﬦ' => 'ם', + 'ﬧ' => 'ר', + 'ﬨ' => 'ת', + '﬩' => '+', + 'ﭏ' => 'אל', + 'ﭐ' => 'ٱ', + 'ﭑ' => 'ٱ', + 'ﭒ' => 'ٻ', + 'ﭓ' => 'ٻ', + 'ﭔ' => 'ٻ', + 'ﭕ' => 'ٻ', + 'ﭖ' => 'پ', + 'ﭗ' => 'پ', + 'ﭘ' => 'پ', + 'ﭙ' => 'پ', + 'ﭚ' => 'ڀ', + 'ﭛ' => 'ڀ', + 'ﭜ' => 'ڀ', + 'ﭝ' => 'ڀ', + 'ﭞ' => 'ٺ', + 'ﭟ' => 'ٺ', + 'ﭠ' => 'ٺ', + 'ﭡ' => 'ٺ', + 'ﭢ' => 'ٿ', + 'ﭣ' => 'ٿ', + 'ﭤ' => 'ٿ', + 'ﭥ' => 'ٿ', + 'ﭦ' => 'ٹ', + 'ﭧ' => 'ٹ', + 'ﭨ' => 'ٹ', + 'ﭩ' => 'ٹ', + 'ﭪ' => 'ڤ', + 'ﭫ' => 'ڤ', + 'ﭬ' => 'ڤ', + 'ﭭ' => 'ڤ', + 'ﭮ' => 'ڦ', + 'ﭯ' => 'ڦ', + 'ﭰ' => 'ڦ', + 'ﭱ' => 'ڦ', + 'ﭲ' => 'ڄ', + 'ﭳ' => 'ڄ', + 'ﭴ' => 'ڄ', + 'ﭵ' => 'ڄ', + 'ﭶ' => 'ڃ', + 'ﭷ' => 'ڃ', + 'ﭸ' => 'ڃ', + 'ﭹ' => 'ڃ', + 'ﭺ' => 'چ', + 'ﭻ' => 'چ', + 'ﭼ' => 'چ', + 'ﭽ' => 'چ', + 'ﭾ' => 'ڇ', + 'ﭿ' => 'ڇ', + 'ﮀ' => 'ڇ', + 'ﮁ' => 'ڇ', + 'ﮂ' => 'ڍ', + 'ﮃ' => 'ڍ', + 'ﮄ' => 'ڌ', + 'ﮅ' => 'ڌ', + 'ﮆ' => 'ڎ', + 'ﮇ' => 'ڎ', + 'ﮈ' => 'ڈ', + 'ﮉ' => 'ڈ', + 'ﮊ' => 'ژ', + 'ﮋ' => 'ژ', + 'ﮌ' => 'ڑ', + 'ﮍ' => 'ڑ', + 'ﮎ' => 'ک', + 'ﮏ' => 'ک', + 'ﮐ' => 'ک', + 'ﮑ' => 'ک', + 'ﮒ' => 'گ', + 'ﮓ' => 'گ', + 'ﮔ' => 'گ', + 'ﮕ' => 'گ', + 'ﮖ' => 'ڳ', + 'ﮗ' => 'ڳ', + 'ﮘ' => 'ڳ', + 'ﮙ' => 'ڳ', + 'ﮚ' => 'ڱ', + 'ﮛ' => 'ڱ', + 'ﮜ' => 'ڱ', + 'ﮝ' => 'ڱ', + 'ﮞ' => 'ں', + 'ﮟ' => 'ں', + 'ﮠ' => 'ڻ', + 'ﮡ' => 'ڻ', + 'ﮢ' => 'ڻ', + 'ﮣ' => 'ڻ', + 'ﮤ' => 'ۀ', + 'ﮥ' => 'ۀ', + 'ﮦ' => 'ہ', + 'ﮧ' => 'ہ', + 'ﮨ' => 'ہ', + 'ﮩ' => 'ہ', + 'ﮪ' => 'ھ', + 'ﮫ' => 'ھ', + 'ﮬ' => 'ھ', + 'ﮭ' => 'ھ', + 'ﮮ' => 'ے', + 'ﮯ' => 'ے', + 'ﮰ' => 'ۓ', + 'ﮱ' => 'ۓ', + 'ﯓ' => 'ڭ', + 'ﯔ' => 'ڭ', + 'ﯕ' => 'ڭ', + 'ﯖ' => 'ڭ', + 'ﯗ' => 'ۇ', + 'ﯘ' => 'ۇ', + 'ﯙ' => 'ۆ', + 'ﯚ' => 'ۆ', + 'ﯛ' => 'ۈ', + 'ﯜ' => 'ۈ', + 'ﯝ' => 'ۇٴ', + 'ﯞ' => 'ۋ', + 'ﯟ' => 'ۋ', + 'ﯠ' => 'ۅ', + 'ﯡ' => 'ۅ', + 'ﯢ' => 'ۉ', + 'ﯣ' => 'ۉ', + 'ﯤ' => 'ې', + 'ﯥ' => 'ې', + 'ﯦ' => 'ې', + 'ﯧ' => 'ې', + 'ﯨ' => 'ى', + 'ﯩ' => 'ى', + 'ﯪ' => 'ئا', + 'ﯫ' => 'ئا', + 'ﯬ' => 'ئە', + 'ﯭ' => 'ئە', + 'ﯮ' => 'ئو', + 'ﯯ' => 'ئو', + 'ﯰ' => 'ئۇ', + 'ﯱ' => 'ئۇ', + 'ﯲ' => 'ئۆ', + 'ﯳ' => 'ئۆ', + 'ﯴ' => 'ئۈ', + 'ﯵ' => 'ئۈ', + 'ﯶ' => 'ئې', + 'ﯷ' => 'ئې', + 'ﯸ' => 'ئې', + 'ﯹ' => 'ئى', + 'ﯺ' => 'ئى', + 'ﯻ' => 'ئى', + 'ﯼ' => 'ی', + 'ﯽ' => 'ی', + 'ﯾ' => 'ی', + 'ﯿ' => 'ی', + 'ﰀ' => 'ئج', + 'ﰁ' => 'ئح', + 'ﰂ' => 'ئم', + 'ﰃ' => 'ئى', + 'ﰄ' => 'ئي', + 'ﰅ' => 'بج', + 'ﰆ' => 'بح', + 'ﰇ' => 'بخ', + 'ﰈ' => 'بم', + 'ﰉ' => 'بى', + 'ﰊ' => 'بي', + 'ﰋ' => 'تج', + 'ﰌ' => 'تح', + 'ﰍ' => 'تخ', + 'ﰎ' => 'تم', + 'ﰏ' => 'تى', + 'ﰐ' => 'تي', + 'ﰑ' => 'ثج', + 'ﰒ' => 'ثم', + 'ﰓ' => 'ثى', + 'ﰔ' => 'ثي', + 'ﰕ' => 'جح', + 'ﰖ' => 'جم', + 'ﰗ' => 'حج', + 'ﰘ' => 'حم', + 'ﰙ' => 'خج', + 'ﰚ' => 'خح', + 'ﰛ' => 'خم', + 'ﰜ' => 'سج', + 'ﰝ' => 'سح', + 'ﰞ' => 'سخ', + 'ﰟ' => 'سم', + 'ﰠ' => 'صح', + 'ﰡ' => 'صم', + 'ﰢ' => 'ضج', + 'ﰣ' => 'ضح', + 'ﰤ' => 'ضخ', + 'ﰥ' => 'ضم', + 'ﰦ' => 'طح', + 'ﰧ' => 'طم', + 'ﰨ' => 'ظم', + 'ﰩ' => 'عج', + 'ﰪ' => 'عم', + 'ﰫ' => 'غج', + 'ﰬ' => 'غم', + 'ﰭ' => 'فج', + 'ﰮ' => 'فح', + 'ﰯ' => 'فخ', + 'ﰰ' => 'فم', + 'ﰱ' => 'فى', + 'ﰲ' => 'في', + 'ﰳ' => 'قح', + 'ﰴ' => 'قم', + 'ﰵ' => 'قى', + 'ﰶ' => 'قي', + 'ﰷ' => 'كا', + 'ﰸ' => 'كج', + 'ﰹ' => 'كح', + 'ﰺ' => 'كخ', + 'ﰻ' => 'كل', + 'ﰼ' => 'كم', + 'ﰽ' => 'كى', + 'ﰾ' => 'كي', + 'ﰿ' => 'لج', + 'ﱀ' => 'لح', + 'ﱁ' => 'لخ', + 'ﱂ' => 'لم', + 'ﱃ' => 'لى', + 'ﱄ' => 'لي', + 'ﱅ' => 'مج', + 'ﱆ' => 'مح', + 'ﱇ' => 'مخ', + 'ﱈ' => 'مم', + 'ﱉ' => 'مى', + 'ﱊ' => 'مي', + 'ﱋ' => 'نج', + 'ﱌ' => 'نح', + 'ﱍ' => 'نخ', + 'ﱎ' => 'نم', + 'ﱏ' => 'نى', + 'ﱐ' => 'ني', + 'ﱑ' => 'هج', + 'ﱒ' => 'هم', + 'ﱓ' => 'هى', + 'ﱔ' => 'هي', + 'ﱕ' => 'يج', + 'ﱖ' => 'يح', + 'ﱗ' => 'يخ', + 'ﱘ' => 'يم', + 'ﱙ' => 'يى', + 'ﱚ' => 'يي', + 'ﱛ' => 'ذٰ', + 'ﱜ' => 'رٰ', + 'ﱝ' => 'ىٰ', + 'ﱞ' => ' ٌّ', + 'ﱟ' => ' ٍّ', + 'ﱠ' => ' َّ', + 'ﱡ' => ' ُّ', + 'ﱢ' => ' ِّ', + 'ﱣ' => ' ّٰ', + 'ﱤ' => 'ئر', + 'ﱥ' => 'ئز', + 'ﱦ' => 'ئم', + 'ﱧ' => 'ئن', + 'ﱨ' => 'ئى', + 'ﱩ' => 'ئي', + 'ﱪ' => 'بر', + 'ﱫ' => 'بز', + 'ﱬ' => 'بم', + 'ﱭ' => 'بن', + 'ﱮ' => 'بى', + 'ﱯ' => 'بي', + 'ﱰ' => 'تر', + 'ﱱ' => 'تز', + 'ﱲ' => 'تم', + 'ﱳ' => 'تن', + 'ﱴ' => 'تى', + 'ﱵ' => 'تي', + 'ﱶ' => 'ثر', + 'ﱷ' => 'ثز', + 'ﱸ' => 'ثم', + 'ﱹ' => 'ثن', + 'ﱺ' => 'ثى', + 'ﱻ' => 'ثي', + 'ﱼ' => 'فى', + 'ﱽ' => 'في', + 'ﱾ' => 'قى', + 'ﱿ' => 'قي', + 'ﲀ' => 'كا', + 'ﲁ' => 'كل', + 'ﲂ' => 'كم', + 'ﲃ' => 'كى', + 'ﲄ' => 'كي', + 'ﲅ' => 'لم', + 'ﲆ' => 'لى', + 'ﲇ' => 'لي', + 'ﲈ' => 'ما', + 'ﲉ' => 'مم', + 'ﲊ' => 'نر', + 'ﲋ' => 'نز', + 'ﲌ' => 'نم', + 'ﲍ' => 'نن', + 'ﲎ' => 'نى', + 'ﲏ' => 'ني', + 'ﲐ' => 'ىٰ', + 'ﲑ' => 'ير', + 'ﲒ' => 'يز', + 'ﲓ' => 'يم', + 'ﲔ' => 'ين', + 'ﲕ' => 'يى', + 'ﲖ' => 'يي', + 'ﲗ' => 'ئج', + 'ﲘ' => 'ئح', + 'ﲙ' => 'ئخ', + 'ﲚ' => 'ئم', + 'ﲛ' => 'ئه', + 'ﲜ' => 'بج', + 'ﲝ' => 'بح', + 'ﲞ' => 'بخ', + 'ﲟ' => 'بم', + 'ﲠ' => 'به', + 'ﲡ' => 'تج', + 'ﲢ' => 'تح', + 'ﲣ' => 'تخ', + 'ﲤ' => 'تم', + 'ﲥ' => 'ته', + 'ﲦ' => 'ثم', + 'ﲧ' => 'جح', + 'ﲨ' => 'جم', + 'ﲩ' => 'حج', + 'ﲪ' => 'حم', + 'ﲫ' => 'خج', + 'ﲬ' => 'خم', + 'ﲭ' => 'سج', + 'ﲮ' => 'سح', + 'ﲯ' => 'سخ', + 'ﲰ' => 'سم', + 'ﲱ' => 'صح', + 'ﲲ' => 'صخ', + 'ﲳ' => 'صم', + 'ﲴ' => 'ضج', + 'ﲵ' => 'ضح', + 'ﲶ' => 'ضخ', + 'ﲷ' => 'ضم', + 'ﲸ' => 'طح', + 'ﲹ' => 'ظم', + 'ﲺ' => 'عج', + 'ﲻ' => 'عم', + 'ﲼ' => 'غج', + 'ﲽ' => 'غم', + 'ﲾ' => 'فج', + 'ﲿ' => 'فح', + 'ﳀ' => 'فخ', + 'ﳁ' => 'فم', + 'ﳂ' => 'قح', + 'ﳃ' => 'قم', + 'ﳄ' => 'كج', + 'ﳅ' => 'كح', + 'ﳆ' => 'كخ', + 'ﳇ' => 'كل', + 'ﳈ' => 'كم', + 'ﳉ' => 'لج', + 'ﳊ' => 'لح', + 'ﳋ' => 'لخ', + 'ﳌ' => 'لم', + 'ﳍ' => 'له', + 'ﳎ' => 'مج', + 'ﳏ' => 'مح', + 'ﳐ' => 'مخ', + 'ﳑ' => 'مم', + 'ﳒ' => 'نج', + 'ﳓ' => 'نح', + 'ﳔ' => 'نخ', + 'ﳕ' => 'نم', + 'ﳖ' => 'نه', + 'ﳗ' => 'هج', + 'ﳘ' => 'هم', + 'ﳙ' => 'هٰ', + 'ﳚ' => 'يج', + 'ﳛ' => 'يح', + 'ﳜ' => 'يخ', + 'ﳝ' => 'يم', + 'ﳞ' => 'يه', + 'ﳟ' => 'ئم', + 'ﳠ' => 'ئه', + 'ﳡ' => 'بم', + 'ﳢ' => 'به', + 'ﳣ' => 'تم', + 'ﳤ' => 'ته', + 'ﳥ' => 'ثم', + 'ﳦ' => 'ثه', + 'ﳧ' => 'سم', + 'ﳨ' => 'سه', + 'ﳩ' => 'شم', + 'ﳪ' => 'شه', + 'ﳫ' => 'كل', + 'ﳬ' => 'كم', + 'ﳭ' => 'لم', + 'ﳮ' => 'نم', + 'ﳯ' => 'نه', + 'ﳰ' => 'يم', + 'ﳱ' => 'يه', + 'ﳲ' => 'ـَّ', + 'ﳳ' => 'ـُّ', + 'ﳴ' => 'ـِّ', + 'ﳵ' => 'طى', + 'ﳶ' => 'طي', + 'ﳷ' => 'عى', + 'ﳸ' => 'عي', + 'ﳹ' => 'غى', + 'ﳺ' => 'غي', + 'ﳻ' => 'سى', + 'ﳼ' => 'سي', + 'ﳽ' => 'شى', + 'ﳾ' => 'شي', + 'ﳿ' => 'حى', + 'ﴀ' => 'حي', + 'ﴁ' => 'جى', + 'ﴂ' => 'جي', + 'ﴃ' => 'خى', + 'ﴄ' => 'خي', + 'ﴅ' => 'صى', + 'ﴆ' => 'صي', + 'ﴇ' => 'ضى', + 'ﴈ' => 'ضي', + 'ﴉ' => 'شج', + 'ﴊ' => 'شح', + 'ﴋ' => 'شخ', + 'ﴌ' => 'شم', + 'ﴍ' => 'شر', + 'ﴎ' => 'سر', + 'ﴏ' => 'صر', + 'ﴐ' => 'ضر', + 'ﴑ' => 'طى', + 'ﴒ' => 'طي', + 'ﴓ' => 'عى', + 'ﴔ' => 'عي', + 'ﴕ' => 'غى', + 'ﴖ' => 'غي', + 'ﴗ' => 'سى', + 'ﴘ' => 'سي', + 'ﴙ' => 'شى', + 'ﴚ' => 'شي', + 'ﴛ' => 'حى', + 'ﴜ' => 'حي', + 'ﴝ' => 'جى', + 'ﴞ' => 'جي', + 'ﴟ' => 'خى', + 'ﴠ' => 'خي', + 'ﴡ' => 'صى', + 'ﴢ' => 'صي', + 'ﴣ' => 'ضى', + 'ﴤ' => 'ضي', + 'ﴥ' => 'شج', + 'ﴦ' => 'شح', + 'ﴧ' => 'شخ', + 'ﴨ' => 'شم', + 'ﴩ' => 'شر', + 'ﴪ' => 'سر', + 'ﴫ' => 'صر', + 'ﴬ' => 'ضر', + 'ﴭ' => 'شج', + 'ﴮ' => 'شح', + 'ﴯ' => 'شخ', + 'ﴰ' => 'شم', + 'ﴱ' => 'سه', + 'ﴲ' => 'شه', + 'ﴳ' => 'طم', + 'ﴴ' => 'سج', + 'ﴵ' => 'سح', + 'ﴶ' => 'سخ', + 'ﴷ' => 'شج', + 'ﴸ' => 'شح', + 'ﴹ' => 'شخ', + 'ﴺ' => 'طم', + 'ﴻ' => 'ظم', + 'ﴼ' => 'اً', + 'ﴽ' => 'اً', + 'ﵐ' => 'تجم', + 'ﵑ' => 'تحج', + 'ﵒ' => 'تحج', + 'ﵓ' => 'تحم', + 'ﵔ' => 'تخم', + 'ﵕ' => 'تمج', + 'ﵖ' => 'تمح', + 'ﵗ' => 'تمخ', + 'ﵘ' => 'جمح', + 'ﵙ' => 'جمح', + 'ﵚ' => 'حمي', + 'ﵛ' => 'حمى', + 'ﵜ' => 'سحج', + 'ﵝ' => 'سجح', + 'ﵞ' => 'سجى', + 'ﵟ' => 'سمح', + 'ﵠ' => 'سمح', + 'ﵡ' => 'سمج', + 'ﵢ' => 'سمم', + 'ﵣ' => 'سمم', + 'ﵤ' => 'صحح', + 'ﵥ' => 'صحح', + 'ﵦ' => 'صمم', + 'ﵧ' => 'شحم', + 'ﵨ' => 'شحم', + 'ﵩ' => 'شجي', + 'ﵪ' => 'شمخ', + 'ﵫ' => 'شمخ', + 'ﵬ' => 'شمم', + 'ﵭ' => 'شمم', + 'ﵮ' => 'ضحى', + 'ﵯ' => 'ضخم', + 'ﵰ' => 'ضخم', + 'ﵱ' => 'طمح', + 'ﵲ' => 'طمح', + 'ﵳ' => 'طمم', + 'ﵴ' => 'طمي', + 'ﵵ' => 'عجم', + 'ﵶ' => 'عمم', + 'ﵷ' => 'عمم', + 'ﵸ' => 'عمى', + 'ﵹ' => 'غمم', + 'ﵺ' => 'غمي', + 'ﵻ' => 'غمى', + 'ﵼ' => 'فخم', + 'ﵽ' => 'فخم', + 'ﵾ' => 'قمح', + 'ﵿ' => 'قمم', + 'ﶀ' => 'لحم', + 'ﶁ' => 'لحي', + 'ﶂ' => 'لحى', + 'ﶃ' => 'لجج', + 'ﶄ' => 'لجج', + 'ﶅ' => 'لخم', + 'ﶆ' => 'لخم', + 'ﶇ' => 'لمح', + 'ﶈ' => 'لمح', + 'ﶉ' => 'محج', + 'ﶊ' => 'محم', + 'ﶋ' => 'محي', + 'ﶌ' => 'مجح', + 'ﶍ' => 'مجم', + 'ﶎ' => 'مخج', + 'ﶏ' => 'مخم', + 'ﶒ' => 'مجخ', + 'ﶓ' => 'همج', + 'ﶔ' => 'همم', + 'ﶕ' => 'نحم', + 'ﶖ' => 'نحى', + 'ﶗ' => 'نجم', + 'ﶘ' => 'نجم', + 'ﶙ' => 'نجى', + 'ﶚ' => 'نمي', + 'ﶛ' => 'نمى', + 'ﶜ' => 'يمم', + 'ﶝ' => 'يمم', + 'ﶞ' => 'بخي', + 'ﶟ' => 'تجي', + 'ﶠ' => 'تجى', + 'ﶡ' => 'تخي', + 'ﶢ' => 'تخى', + 'ﶣ' => 'تمي', + 'ﶤ' => 'تمى', + 'ﶥ' => 'جمي', + 'ﶦ' => 'جحى', + 'ﶧ' => 'جمى', + 'ﶨ' => 'سخى', + 'ﶩ' => 'صحي', + 'ﶪ' => 'شحي', + 'ﶫ' => 'ضحي', + 'ﶬ' => 'لجي', + 'ﶭ' => 'لمي', + 'ﶮ' => 'يحي', + 'ﶯ' => 'يجي', + 'ﶰ' => 'يمي', + 'ﶱ' => 'ممي', + 'ﶲ' => 'قمي', + 'ﶳ' => 'نحي', + 'ﶴ' => 'قمح', + 'ﶵ' => 'لحم', + 'ﶶ' => 'عمي', + 'ﶷ' => 'كمي', + 'ﶸ' => 'نجح', + 'ﶹ' => 'مخي', + 'ﶺ' => 'لجم', + 'ﶻ' => 'كمم', + 'ﶼ' => 'لجم', + 'ﶽ' => 'نجح', + 'ﶾ' => 'جحي', + 'ﶿ' => 'حجي', + 'ﷀ' => 'مجي', + 'ﷁ' => 'فمي', + 'ﷂ' => 'بحي', + 'ﷃ' => 'كمم', + 'ﷄ' => 'عجم', + 'ﷅ' => 'صمم', + 'ﷆ' => 'سخي', + 'ﷇ' => 'نجي', + 'ﷰ' => 'صلے', + 'ﷱ' => 'قلے', + 'ﷲ' => 'الله', + 'ﷳ' => 'اكبر', + 'ﷴ' => 'محمد', + 'ﷵ' => 'صلعم', + 'ﷶ' => 'رسول', + 'ﷷ' => 'عليه', + 'ﷸ' => 'وسلم', + 'ﷹ' => 'صلى', + 'ﷺ' => 'صلى الله عليه وسلم', + 'ﷻ' => 'جل جلاله', + '﷼' => 'ریال', + '︐' => ',', + '︑' => '、', + '︒' => '。', + '︓' => ':', + '︔' => ';', + '︕' => '!', + '︖' => '?', + '︗' => '〖', + '︘' => '〗', + '︙' => '...', + '︰' => '..', + '︱' => '—', + '︲' => '–', + '︳' => '_', + '︴' => '_', + '︵' => '(', + '︶' => ')', + '︷' => '{', + '︸' => '}', + '︹' => '〔', + '︺' => '〕', + '︻' => '【', + '︼' => '】', + '︽' => '《', + '︾' => '》', + '︿' => '〈', + '﹀' => '〉', + '﹁' => '「', + '﹂' => '」', + '﹃' => '『', + '﹄' => '』', + '﹇' => '[', + '﹈' => ']', + '﹉' => ' ̅', + '﹊' => ' ̅', + '﹋' => ' ̅', + '﹌' => ' ̅', + '﹍' => '_', + '﹎' => '_', + '﹏' => '_', + '﹐' => ',', + '﹑' => '、', + '﹒' => '.', + '﹔' => ';', + '﹕' => ':', + '﹖' => '?', + '﹗' => '!', + '﹘' => '—', + '﹙' => '(', + '﹚' => ')', + '﹛' => '{', + '﹜' => '}', + '﹝' => '〔', + '﹞' => '〕', + '﹟' => '#', + '﹠' => '&', + '﹡' => '*', + '﹢' => '+', + '﹣' => '-', + '﹤' => '<', + '﹥' => '>', + '﹦' => '=', + '﹨' => '\\', + '﹩' => '$', + '﹪' => '%', + '﹫' => '@', + 'ﹰ' => ' ً', + 'ﹱ' => 'ـً', + 'ﹲ' => ' ٌ', + 'ﹴ' => ' ٍ', + 'ﹶ' => ' َ', + 'ﹷ' => 'ـَ', + 'ﹸ' => ' ُ', + 'ﹹ' => 'ـُ', + 'ﹺ' => ' ِ', + 'ﹻ' => 'ـِ', + 'ﹼ' => ' ّ', + 'ﹽ' => 'ـّ', + 'ﹾ' => ' ْ', + 'ﹿ' => 'ـْ', + 'ﺀ' => 'ء', + 'ﺁ' => 'آ', + 'ﺂ' => 'آ', + 'ﺃ' => 'أ', + 'ﺄ' => 'أ', + 'ﺅ' => 'ؤ', + 'ﺆ' => 'ؤ', + 'ﺇ' => 'إ', + 'ﺈ' => 'إ', + 'ﺉ' => 'ئ', + 'ﺊ' => 'ئ', + 'ﺋ' => 'ئ', + 'ﺌ' => 'ئ', + 'ﺍ' => 'ا', + 'ﺎ' => 'ا', + 'ﺏ' => 'ب', + 'ﺐ' => 'ب', + 'ﺑ' => 'ب', + 'ﺒ' => 'ب', + 'ﺓ' => 'ة', + 'ﺔ' => 'ة', + 'ﺕ' => 'ت', + 'ﺖ' => 'ت', + 'ﺗ' => 'ت', + 'ﺘ' => 'ت', + 'ﺙ' => 'ث', + 'ﺚ' => 'ث', + 'ﺛ' => 'ث', + 'ﺜ' => 'ث', + 'ﺝ' => 'ج', + 'ﺞ' => 'ج', + 'ﺟ' => 'ج', + 'ﺠ' => 'ج', + 'ﺡ' => 'ح', + 'ﺢ' => 'ح', + 'ﺣ' => 'ح', + 'ﺤ' => 'ح', + 'ﺥ' => 'خ', + 'ﺦ' => 'خ', + 'ﺧ' => 'خ', + 'ﺨ' => 'خ', + 'ﺩ' => 'د', + 'ﺪ' => 'د', + 'ﺫ' => 'ذ', + 'ﺬ' => 'ذ', + 'ﺭ' => 'ر', + 'ﺮ' => 'ر', + 'ﺯ' => 'ز', + 'ﺰ' => 'ز', + 'ﺱ' => 'س', + 'ﺲ' => 'س', + 'ﺳ' => 'س', + 'ﺴ' => 'س', + 'ﺵ' => 'ش', + 'ﺶ' => 'ش', + 'ﺷ' => 'ش', + 'ﺸ' => 'ش', + 'ﺹ' => 'ص', + 'ﺺ' => 'ص', + 'ﺻ' => 'ص', + 'ﺼ' => 'ص', + 'ﺽ' => 'ض', + 'ﺾ' => 'ض', + 'ﺿ' => 'ض', + 'ﻀ' => 'ض', + 'ﻁ' => 'ط', + 'ﻂ' => 'ط', + 'ﻃ' => 'ط', + 'ﻄ' => 'ط', + 'ﻅ' => 'ظ', + 'ﻆ' => 'ظ', + 'ﻇ' => 'ظ', + 'ﻈ' => 'ظ', + 'ﻉ' => 'ع', + 'ﻊ' => 'ع', + 'ﻋ' => 'ع', + 'ﻌ' => 'ع', + 'ﻍ' => 'غ', + 'ﻎ' => 'غ', + 'ﻏ' => 'غ', + 'ﻐ' => 'غ', + 'ﻑ' => 'ف', + 'ﻒ' => 'ف', + 'ﻓ' => 'ف', + 'ﻔ' => 'ف', + 'ﻕ' => 'ق', + 'ﻖ' => 'ق', + 'ﻗ' => 'ق', + 'ﻘ' => 'ق', + 'ﻙ' => 'ك', + 'ﻚ' => 'ك', + 'ﻛ' => 'ك', + 'ﻜ' => 'ك', + 'ﻝ' => 'ل', + 'ﻞ' => 'ل', + 'ﻟ' => 'ل', + 'ﻠ' => 'ل', + 'ﻡ' => 'م', + 'ﻢ' => 'م', + 'ﻣ' => 'م', + 'ﻤ' => 'م', + 'ﻥ' => 'ن', + 'ﻦ' => 'ن', + 'ﻧ' => 'ن', + 'ﻨ' => 'ن', + 'ﻩ' => 'ه', + 'ﻪ' => 'ه', + 'ﻫ' => 'ه', + 'ﻬ' => 'ه', + 'ﻭ' => 'و', + 'ﻮ' => 'و', + 'ﻯ' => 'ى', + 'ﻰ' => 'ى', + 'ﻱ' => 'ي', + 'ﻲ' => 'ي', + 'ﻳ' => 'ي', + 'ﻴ' => 'ي', + 'ﻵ' => 'لآ', + 'ﻶ' => 'لآ', + 'ﻷ' => 'لأ', + 'ﻸ' => 'لأ', + 'ﻹ' => 'لإ', + 'ﻺ' => 'لإ', + 'ﻻ' => 'لا', + 'ﻼ' => 'لا', + '!' => '!', + '"' => '"', + '#' => '#', + '$' => '$', + '%' => '%', + '&' => '&', + ''' => '\'', + '(' => '(', + ')' => ')', + '*' => '*', + '+' => '+', + ',' => ',', + '-' => '-', + '.' => '.', + '/' => '/', + '0' => '0', + '1' => '1', + '2' => '2', + '3' => '3', + '4' => '4', + '5' => '5', + '6' => '6', + '7' => '7', + '8' => '8', + '9' => '9', + ':' => ':', + ';' => ';', + '<' => '<', + '=' => '=', + '>' => '>', + '?' => '?', + '@' => '@', + 'A' => 'A', + 'B' => 'B', + 'C' => 'C', + 'D' => 'D', + 'E' => 'E', + 'F' => 'F', + 'G' => 'G', + 'H' => 'H', + 'I' => 'I', + 'J' => 'J', + 'K' => 'K', + 'L' => 'L', + 'M' => 'M', + 'N' => 'N', + 'O' => 'O', + 'P' => 'P', + 'Q' => 'Q', + 'R' => 'R', + 'S' => 'S', + 'T' => 'T', + 'U' => 'U', + 'V' => 'V', + 'W' => 'W', + 'X' => 'X', + 'Y' => 'Y', + 'Z' => 'Z', + '[' => '[', + '\' => '\\', + ']' => ']', + '^' => '^', + '_' => '_', + '`' => '`', + 'a' => 'a', + 'b' => 'b', + 'c' => 'c', + 'd' => 'd', + 'e' => 'e', + 'f' => 'f', + 'g' => 'g', + 'h' => 'h', + 'i' => 'i', + 'j' => 'j', + 'k' => 'k', + 'l' => 'l', + 'm' => 'm', + 'n' => 'n', + 'o' => 'o', + 'p' => 'p', + 'q' => 'q', + 'r' => 'r', + 's' => 's', + 't' => 't', + 'u' => 'u', + 'v' => 'v', + 'w' => 'w', + 'x' => 'x', + 'y' => 'y', + 'z' => 'z', + '{' => '{', + '|' => '|', + '}' => '}', + '~' => '~', + '⦅' => '⦅', + '⦆' => '⦆', + '。' => '。', + '「' => '「', + '」' => '」', + '、' => '、', + '・' => '・', + 'ヲ' => 'ヲ', + 'ァ' => 'ァ', + 'ィ' => 'ィ', + 'ゥ' => 'ゥ', + 'ェ' => 'ェ', + 'ォ' => 'ォ', + 'ャ' => 'ャ', + 'ュ' => 'ュ', + 'ョ' => 'ョ', + 'ッ' => 'ッ', + 'ー' => 'ー', + 'ア' => 'ア', + 'イ' => 'イ', + 'ウ' => 'ウ', + 'エ' => 'エ', + 'オ' => 'オ', + 'カ' => 'カ', + 'キ' => 'キ', + 'ク' => 'ク', + 'ケ' => 'ケ', + 'コ' => 'コ', + 'サ' => 'サ', + 'シ' => 'シ', + 'ス' => 'ス', + 'セ' => 'セ', + 'ソ' => 'ソ', + 'タ' => 'タ', + 'チ' => 'チ', + 'ツ' => 'ツ', + 'テ' => 'テ', + 'ト' => 'ト', + 'ナ' => 'ナ', + 'ニ' => 'ニ', + 'ヌ' => 'ヌ', + 'ネ' => 'ネ', + 'ノ' => 'ノ', + 'ハ' => 'ハ', + 'ヒ' => 'ヒ', + 'フ' => 'フ', + 'ヘ' => 'ヘ', + 'ホ' => 'ホ', + 'マ' => 'マ', + 'ミ' => 'ミ', + 'ム' => 'ム', + 'メ' => 'メ', + 'モ' => 'モ', + 'ヤ' => 'ヤ', + 'ユ' => 'ユ', + 'ヨ' => 'ヨ', + 'ラ' => 'ラ', + 'リ' => 'リ', + 'ル' => 'ル', + 'レ' => 'レ', + 'ロ' => 'ロ', + 'ワ' => 'ワ', + 'ン' => 'ン', + '゙' => '゙', + '゚' => '゚', + 'ᅠ' => 'ᅠ', + 'ᄀ' => 'ᄀ', + 'ᄁ' => 'ᄁ', + 'ᆪ' => 'ᆪ', + 'ᄂ' => 'ᄂ', + 'ᆬ' => 'ᆬ', + 'ᆭ' => 'ᆭ', + 'ᄃ' => 'ᄃ', + 'ᄄ' => 'ᄄ', + 'ᄅ' => 'ᄅ', + 'ᆰ' => 'ᆰ', + 'ᆱ' => 'ᆱ', + 'ᆲ' => 'ᆲ', + 'ᆳ' => 'ᆳ', + 'ᆴ' => 'ᆴ', + 'ᆵ' => 'ᆵ', + 'ᄚ' => 'ᄚ', + 'ᄆ' => 'ᄆ', + 'ᄇ' => 'ᄇ', + 'ᄈ' => 'ᄈ', + 'ᄡ' => 'ᄡ', + 'ᄉ' => 'ᄉ', + 'ᄊ' => 'ᄊ', + 'ᄋ' => 'ᄋ', + 'ᄌ' => 'ᄌ', + 'ᄍ' => 'ᄍ', + 'ᄎ' => 'ᄎ', + 'ᄏ' => 'ᄏ', + 'ᄐ' => 'ᄐ', + 'ᄑ' => 'ᄑ', + 'ᄒ' => 'ᄒ', + 'ᅡ' => 'ᅡ', + 'ᅢ' => 'ᅢ', + 'ᅣ' => 'ᅣ', + 'ᅤ' => 'ᅤ', + 'ᅥ' => 'ᅥ', + 'ᅦ' => 'ᅦ', + 'ᅧ' => 'ᅧ', + 'ᅨ' => 'ᅨ', + 'ᅩ' => 'ᅩ', + 'ᅪ' => 'ᅪ', + 'ᅫ' => 'ᅫ', + 'ᅬ' => 'ᅬ', + 'ᅭ' => 'ᅭ', + 'ᅮ' => 'ᅮ', + 'ᅯ' => 'ᅯ', + 'ᅰ' => 'ᅰ', + 'ᅱ' => 'ᅱ', + 'ᅲ' => 'ᅲ', + 'ᅳ' => 'ᅳ', + 'ᅴ' => 'ᅴ', + 'ᅵ' => 'ᅵ', + '¢' => '¢', + '£' => '£', + '¬' => '¬', + ' ̄' => ' ̄', + '¦' => '¦', + '¥' => '¥', + '₩' => '₩', + '│' => '│', + '←' => '←', + '↑' => '↑', + '→' => '→', + '↓' => '↓', + '■' => '■', + '○' => '○', + '𝐀' => 'A', + '𝐁' => 'B', + '𝐂' => 'C', + '𝐃' => 'D', + '𝐄' => 'E', + '𝐅' => 'F', + '𝐆' => 'G', + '𝐇' => 'H', + '𝐈' => 'I', + '𝐉' => 'J', + '𝐊' => 'K', + '𝐋' => 'L', + '𝐌' => 'M', + '𝐍' => 'N', + '𝐎' => 'O', + '𝐏' => 'P', + '𝐐' => 'Q', + '𝐑' => 'R', + '𝐒' => 'S', + '𝐓' => 'T', + '𝐔' => 'U', + '𝐕' => 'V', + '𝐖' => 'W', + '𝐗' => 'X', + '𝐘' => 'Y', + '𝐙' => 'Z', + '𝐚' => 'a', + '𝐛' => 'b', + '𝐜' => 'c', + '𝐝' => 'd', + '𝐞' => 'e', + '𝐟' => 'f', + '𝐠' => 'g', + '𝐡' => 'h', + '𝐢' => 'i', + '𝐣' => 'j', + '𝐤' => 'k', + '𝐥' => 'l', + '𝐦' => 'm', + '𝐧' => 'n', + '𝐨' => 'o', + '𝐩' => 'p', + '𝐪' => 'q', + '𝐫' => 'r', + '𝐬' => 's', + '𝐭' => 't', + '𝐮' => 'u', + '𝐯' => 'v', + '𝐰' => 'w', + '𝐱' => 'x', + '𝐲' => 'y', + '𝐳' => 'z', + '𝐴' => 'A', + '𝐵' => 'B', + '𝐶' => 'C', + '𝐷' => 'D', + '𝐸' => 'E', + '𝐹' => 'F', + '𝐺' => 'G', + '𝐻' => 'H', + '𝐼' => 'I', + '𝐽' => 'J', + '𝐾' => 'K', + '𝐿' => 'L', + '𝑀' => 'M', + '𝑁' => 'N', + '𝑂' => 'O', + '𝑃' => 'P', + '𝑄' => 'Q', + '𝑅' => 'R', + '𝑆' => 'S', + '𝑇' => 'T', + '𝑈' => 'U', + '𝑉' => 'V', + '𝑊' => 'W', + '𝑋' => 'X', + '𝑌' => 'Y', + '𝑍' => 'Z', + '𝑎' => 'a', + '𝑏' => 'b', + '𝑐' => 'c', + '𝑑' => 'd', + '𝑒' => 'e', + '𝑓' => 'f', + '𝑔' => 'g', + '𝑖' => 'i', + '𝑗' => 'j', + '𝑘' => 'k', + '𝑙' => 'l', + '𝑚' => 'm', + '𝑛' => 'n', + '𝑜' => 'o', + '𝑝' => 'p', + '𝑞' => 'q', + '𝑟' => 'r', + '𝑠' => 's', + '𝑡' => 't', + '𝑢' => 'u', + '𝑣' => 'v', + '𝑤' => 'w', + '𝑥' => 'x', + '𝑦' => 'y', + '𝑧' => 'z', + '𝑨' => 'A', + '𝑩' => 'B', + '𝑪' => 'C', + '𝑫' => 'D', + '𝑬' => 'E', + '𝑭' => 'F', + '𝑮' => 'G', + '𝑯' => 'H', + '𝑰' => 'I', + '𝑱' => 'J', + '𝑲' => 'K', + '𝑳' => 'L', + '𝑴' => 'M', + '𝑵' => 'N', + '𝑶' => 'O', + '𝑷' => 'P', + '𝑸' => 'Q', + '𝑹' => 'R', + '𝑺' => 'S', + '𝑻' => 'T', + '𝑼' => 'U', + '𝑽' => 'V', + '𝑾' => 'W', + '𝑿' => 'X', + '𝒀' => 'Y', + '𝒁' => 'Z', + '𝒂' => 'a', + '𝒃' => 'b', + '𝒄' => 'c', + '𝒅' => 'd', + '𝒆' => 'e', + '𝒇' => 'f', + '𝒈' => 'g', + '𝒉' => 'h', + '𝒊' => 'i', + '𝒋' => 'j', + '𝒌' => 'k', + '𝒍' => 'l', + '𝒎' => 'm', + '𝒏' => 'n', + '𝒐' => 'o', + '𝒑' => 'p', + '𝒒' => 'q', + '𝒓' => 'r', + '𝒔' => 's', + '𝒕' => 't', + '𝒖' => 'u', + '𝒗' => 'v', + '𝒘' => 'w', + '𝒙' => 'x', + '𝒚' => 'y', + '𝒛' => 'z', + '𝒜' => 'A', + '𝒞' => 'C', + '𝒟' => 'D', + '𝒢' => 'G', + '𝒥' => 'J', + '𝒦' => 'K', + '𝒩' => 'N', + '𝒪' => 'O', + '𝒫' => 'P', + '𝒬' => 'Q', + '𝒮' => 'S', + '𝒯' => 'T', + '𝒰' => 'U', + '𝒱' => 'V', + '𝒲' => 'W', + '𝒳' => 'X', + '𝒴' => 'Y', + '𝒵' => 'Z', + '𝒶' => 'a', + '𝒷' => 'b', + '𝒸' => 'c', + '𝒹' => 'd', + '𝒻' => 'f', + '𝒽' => 'h', + '𝒾' => 'i', + '𝒿' => 'j', + '𝓀' => 'k', + '𝓁' => 'l', + '𝓂' => 'm', + '𝓃' => 'n', + '𝓅' => 'p', + '𝓆' => 'q', + '𝓇' => 'r', + '𝓈' => 's', + '𝓉' => 't', + '𝓊' => 'u', + '𝓋' => 'v', + '𝓌' => 'w', + '𝓍' => 'x', + '𝓎' => 'y', + '𝓏' => 'z', + '𝓐' => 'A', + '𝓑' => 'B', + '𝓒' => 'C', + '𝓓' => 'D', + '𝓔' => 'E', + '𝓕' => 'F', + '𝓖' => 'G', + '𝓗' => 'H', + '𝓘' => 'I', + '𝓙' => 'J', + '𝓚' => 'K', + '𝓛' => 'L', + '𝓜' => 'M', + '𝓝' => 'N', + '𝓞' => 'O', + '𝓟' => 'P', + '𝓠' => 'Q', + '𝓡' => 'R', + '𝓢' => 'S', + '𝓣' => 'T', + '𝓤' => 'U', + '𝓥' => 'V', + '𝓦' => 'W', + '𝓧' => 'X', + '𝓨' => 'Y', + '𝓩' => 'Z', + '𝓪' => 'a', + '𝓫' => 'b', + '𝓬' => 'c', + '𝓭' => 'd', + '𝓮' => 'e', + '𝓯' => 'f', + '𝓰' => 'g', + '𝓱' => 'h', + '𝓲' => 'i', + '𝓳' => 'j', + '𝓴' => 'k', + '𝓵' => 'l', + '𝓶' => 'm', + '𝓷' => 'n', + '𝓸' => 'o', + '𝓹' => 'p', + '𝓺' => 'q', + '𝓻' => 'r', + '𝓼' => 's', + '𝓽' => 't', + '𝓾' => 'u', + '𝓿' => 'v', + '𝔀' => 'w', + '𝔁' => 'x', + '𝔂' => 'y', + '𝔃' => 'z', + '𝔄' => 'A', + '𝔅' => 'B', + '𝔇' => 'D', + '𝔈' => 'E', + '𝔉' => 'F', + '𝔊' => 'G', + '𝔍' => 'J', + '𝔎' => 'K', + '𝔏' => 'L', + '𝔐' => 'M', + '𝔑' => 'N', + '𝔒' => 'O', + '𝔓' => 'P', + '𝔔' => 'Q', + '𝔖' => 'S', + '𝔗' => 'T', + '𝔘' => 'U', + '𝔙' => 'V', + '𝔚' => 'W', + '𝔛' => 'X', + '𝔜' => 'Y', + '𝔞' => 'a', + '𝔟' => 'b', + '𝔠' => 'c', + '𝔡' => 'd', + '𝔢' => 'e', + '𝔣' => 'f', + '𝔤' => 'g', + '𝔥' => 'h', + '𝔦' => 'i', + '𝔧' => 'j', + '𝔨' => 'k', + '𝔩' => 'l', + '𝔪' => 'm', + '𝔫' => 'n', + '𝔬' => 'o', + '𝔭' => 'p', + '𝔮' => 'q', + '𝔯' => 'r', + '𝔰' => 's', + '𝔱' => 't', + '𝔲' => 'u', + '𝔳' => 'v', + '𝔴' => 'w', + '𝔵' => 'x', + '𝔶' => 'y', + '𝔷' => 'z', + '𝔸' => 'A', + '𝔹' => 'B', + '𝔻' => 'D', + '𝔼' => 'E', + '𝔽' => 'F', + '𝔾' => 'G', + '𝕀' => 'I', + '𝕁' => 'J', + '𝕂' => 'K', + '𝕃' => 'L', + '𝕄' => 'M', + '𝕆' => 'O', + '𝕊' => 'S', + '𝕋' => 'T', + '𝕌' => 'U', + '𝕍' => 'V', + '𝕎' => 'W', + '𝕏' => 'X', + '𝕐' => 'Y', + '𝕒' => 'a', + '𝕓' => 'b', + '𝕔' => 'c', + '𝕕' => 'd', + '𝕖' => 'e', + '𝕗' => 'f', + '𝕘' => 'g', + '𝕙' => 'h', + '𝕚' => 'i', + '𝕛' => 'j', + '𝕜' => 'k', + '𝕝' => 'l', + '𝕞' => 'm', + '𝕟' => 'n', + '𝕠' => 'o', + '𝕡' => 'p', + '𝕢' => 'q', + '𝕣' => 'r', + '𝕤' => 's', + '𝕥' => 't', + '𝕦' => 'u', + '𝕧' => 'v', + '𝕨' => 'w', + '𝕩' => 'x', + '𝕪' => 'y', + '𝕫' => 'z', + '𝕬' => 'A', + '𝕭' => 'B', + '𝕮' => 'C', + '𝕯' => 'D', + '𝕰' => 'E', + '𝕱' => 'F', + '𝕲' => 'G', + '𝕳' => 'H', + '𝕴' => 'I', + '𝕵' => 'J', + '𝕶' => 'K', + '𝕷' => 'L', + '𝕸' => 'M', + '𝕹' => 'N', + '𝕺' => 'O', + '𝕻' => 'P', + '𝕼' => 'Q', + '𝕽' => 'R', + '𝕾' => 'S', + '𝕿' => 'T', + '𝖀' => 'U', + '𝖁' => 'V', + '𝖂' => 'W', + '𝖃' => 'X', + '𝖄' => 'Y', + '𝖅' => 'Z', + '𝖆' => 'a', + '𝖇' => 'b', + '𝖈' => 'c', + '𝖉' => 'd', + '𝖊' => 'e', + '𝖋' => 'f', + '𝖌' => 'g', + '𝖍' => 'h', + '𝖎' => 'i', + '𝖏' => 'j', + '𝖐' => 'k', + '𝖑' => 'l', + '𝖒' => 'm', + '𝖓' => 'n', + '𝖔' => 'o', + '𝖕' => 'p', + '𝖖' => 'q', + '𝖗' => 'r', + '𝖘' => 's', + '𝖙' => 't', + '𝖚' => 'u', + '𝖛' => 'v', + '𝖜' => 'w', + '𝖝' => 'x', + '𝖞' => 'y', + '𝖟' => 'z', + '𝖠' => 'A', + '𝖡' => 'B', + '𝖢' => 'C', + '𝖣' => 'D', + '𝖤' => 'E', + '𝖥' => 'F', + '𝖦' => 'G', + '𝖧' => 'H', + '𝖨' => 'I', + '𝖩' => 'J', + '𝖪' => 'K', + '𝖫' => 'L', + '𝖬' => 'M', + '𝖭' => 'N', + '𝖮' => 'O', + '𝖯' => 'P', + '𝖰' => 'Q', + '𝖱' => 'R', + '𝖲' => 'S', + '𝖳' => 'T', + '𝖴' => 'U', + '𝖵' => 'V', + '𝖶' => 'W', + '𝖷' => 'X', + '𝖸' => 'Y', + '𝖹' => 'Z', + '𝖺' => 'a', + '𝖻' => 'b', + '𝖼' => 'c', + '𝖽' => 'd', + '𝖾' => 'e', + '𝖿' => 'f', + '𝗀' => 'g', + '𝗁' => 'h', + '𝗂' => 'i', + '𝗃' => 'j', + '𝗄' => 'k', + '𝗅' => 'l', + '𝗆' => 'm', + '𝗇' => 'n', + '𝗈' => 'o', + '𝗉' => 'p', + '𝗊' => 'q', + '𝗋' => 'r', + '𝗌' => 's', + '𝗍' => 't', + '𝗎' => 'u', + '𝗏' => 'v', + '𝗐' => 'w', + '𝗑' => 'x', + '𝗒' => 'y', + '𝗓' => 'z', + '𝗔' => 'A', + '𝗕' => 'B', + '𝗖' => 'C', + '𝗗' => 'D', + '𝗘' => 'E', + '𝗙' => 'F', + '𝗚' => 'G', + '𝗛' => 'H', + '𝗜' => 'I', + '𝗝' => 'J', + '𝗞' => 'K', + '𝗟' => 'L', + '𝗠' => 'M', + '𝗡' => 'N', + '𝗢' => 'O', + '𝗣' => 'P', + '𝗤' => 'Q', + '𝗥' => 'R', + '𝗦' => 'S', + '𝗧' => 'T', + '𝗨' => 'U', + '𝗩' => 'V', + '𝗪' => 'W', + '𝗫' => 'X', + '𝗬' => 'Y', + '𝗭' => 'Z', + '𝗮' => 'a', + '𝗯' => 'b', + '𝗰' => 'c', + '𝗱' => 'd', + '𝗲' => 'e', + '𝗳' => 'f', + '𝗴' => 'g', + '𝗵' => 'h', + '𝗶' => 'i', + '𝗷' => 'j', + '𝗸' => 'k', + '𝗹' => 'l', + '𝗺' => 'm', + '𝗻' => 'n', + '𝗼' => 'o', + '𝗽' => 'p', + '𝗾' => 'q', + '𝗿' => 'r', + '𝘀' => 's', + '𝘁' => 't', + '𝘂' => 'u', + '𝘃' => 'v', + '𝘄' => 'w', + '𝘅' => 'x', + '𝘆' => 'y', + '𝘇' => 'z', + '𝘈' => 'A', + '𝘉' => 'B', + '𝘊' => 'C', + '𝘋' => 'D', + '𝘌' => 'E', + '𝘍' => 'F', + '𝘎' => 'G', + '𝘏' => 'H', + '𝘐' => 'I', + '𝘑' => 'J', + '𝘒' => 'K', + '𝘓' => 'L', + '𝘔' => 'M', + '𝘕' => 'N', + '𝘖' => 'O', + '𝘗' => 'P', + '𝘘' => 'Q', + '𝘙' => 'R', + '𝘚' => 'S', + '𝘛' => 'T', + '𝘜' => 'U', + '𝘝' => 'V', + '𝘞' => 'W', + '𝘟' => 'X', + '𝘠' => 'Y', + '𝘡' => 'Z', + '𝘢' => 'a', + '𝘣' => 'b', + '𝘤' => 'c', + '𝘥' => 'd', + '𝘦' => 'e', + '𝘧' => 'f', + '𝘨' => 'g', + '𝘩' => 'h', + '𝘪' => 'i', + '𝘫' => 'j', + '𝘬' => 'k', + '𝘭' => 'l', + '𝘮' => 'm', + '𝘯' => 'n', + '𝘰' => 'o', + '𝘱' => 'p', + '𝘲' => 'q', + '𝘳' => 'r', + '𝘴' => 's', + '𝘵' => 't', + '𝘶' => 'u', + '𝘷' => 'v', + '𝘸' => 'w', + '𝘹' => 'x', + '𝘺' => 'y', + '𝘻' => 'z', + '𝘼' => 'A', + '𝘽' => 'B', + '𝘾' => 'C', + '𝘿' => 'D', + '𝙀' => 'E', + '𝙁' => 'F', + '𝙂' => 'G', + '𝙃' => 'H', + '𝙄' => 'I', + '𝙅' => 'J', + '𝙆' => 'K', + '𝙇' => 'L', + '𝙈' => 'M', + '𝙉' => 'N', + '𝙊' => 'O', + '𝙋' => 'P', + '𝙌' => 'Q', + '𝙍' => 'R', + '𝙎' => 'S', + '𝙏' => 'T', + '𝙐' => 'U', + '𝙑' => 'V', + '𝙒' => 'W', + '𝙓' => 'X', + '𝙔' => 'Y', + '𝙕' => 'Z', + '𝙖' => 'a', + '𝙗' => 'b', + '𝙘' => 'c', + '𝙙' => 'd', + '𝙚' => 'e', + '𝙛' => 'f', + '𝙜' => 'g', + '𝙝' => 'h', + '𝙞' => 'i', + '𝙟' => 'j', + '𝙠' => 'k', + '𝙡' => 'l', + '𝙢' => 'm', + '𝙣' => 'n', + '𝙤' => 'o', + '𝙥' => 'p', + '𝙦' => 'q', + '𝙧' => 'r', + '𝙨' => 's', + '𝙩' => 't', + '𝙪' => 'u', + '𝙫' => 'v', + '𝙬' => 'w', + '𝙭' => 'x', + '𝙮' => 'y', + '𝙯' => 'z', + '𝙰' => 'A', + '𝙱' => 'B', + '𝙲' => 'C', + '𝙳' => 'D', + '𝙴' => 'E', + '𝙵' => 'F', + '𝙶' => 'G', + '𝙷' => 'H', + '𝙸' => 'I', + '𝙹' => 'J', + '𝙺' => 'K', + '𝙻' => 'L', + '𝙼' => 'M', + '𝙽' => 'N', + '𝙾' => 'O', + '𝙿' => 'P', + '𝚀' => 'Q', + '𝚁' => 'R', + '𝚂' => 'S', + '𝚃' => 'T', + '𝚄' => 'U', + '𝚅' => 'V', + '𝚆' => 'W', + '𝚇' => 'X', + '𝚈' => 'Y', + '𝚉' => 'Z', + '𝚊' => 'a', + '𝚋' => 'b', + '𝚌' => 'c', + '𝚍' => 'd', + '𝚎' => 'e', + '𝚏' => 'f', + '𝚐' => 'g', + '𝚑' => 'h', + '𝚒' => 'i', + '𝚓' => 'j', + '𝚔' => 'k', + '𝚕' => 'l', + '𝚖' => 'm', + '𝚗' => 'n', + '𝚘' => 'o', + '𝚙' => 'p', + '𝚚' => 'q', + '𝚛' => 'r', + '𝚜' => 's', + '𝚝' => 't', + '𝚞' => 'u', + '𝚟' => 'v', + '𝚠' => 'w', + '𝚡' => 'x', + '𝚢' => 'y', + '𝚣' => 'z', + '𝚤' => 'ı', + '𝚥' => 'ȷ', + '𝚨' => 'Α', + '𝚩' => 'Β', + '𝚪' => 'Γ', + '𝚫' => 'Δ', + '𝚬' => 'Ε', + '𝚭' => 'Ζ', + '𝚮' => 'Η', + '𝚯' => 'Θ', + '𝚰' => 'Ι', + '𝚱' => 'Κ', + '𝚲' => 'Λ', + '𝚳' => 'Μ', + '𝚴' => 'Ν', + '𝚵' => 'Ξ', + '𝚶' => 'Ο', + '𝚷' => 'Π', + '𝚸' => 'Ρ', + '𝚹' => 'Θ', + '𝚺' => 'Σ', + '𝚻' => 'Τ', + '𝚼' => 'Υ', + '𝚽' => 'Φ', + '𝚾' => 'Χ', + '𝚿' => 'Ψ', + '𝛀' => 'Ω', + '𝛁' => '∇', + '𝛂' => 'α', + '𝛃' => 'β', + '𝛄' => 'γ', + '𝛅' => 'δ', + '𝛆' => 'ε', + '𝛇' => 'ζ', + '𝛈' => 'η', + '𝛉' => 'θ', + '𝛊' => 'ι', + '𝛋' => 'κ', + '𝛌' => 'λ', + '𝛍' => 'μ', + '𝛎' => 'ν', + '𝛏' => 'ξ', + '𝛐' => 'ο', + '𝛑' => 'π', + '𝛒' => 'ρ', + '𝛓' => 'ς', + '𝛔' => 'σ', + '𝛕' => 'τ', + '𝛖' => 'υ', + '𝛗' => 'φ', + '𝛘' => 'χ', + '𝛙' => 'ψ', + '𝛚' => 'ω', + '𝛛' => '∂', + '𝛜' => 'ε', + '𝛝' => 'θ', + '𝛞' => 'κ', + '𝛟' => 'φ', + '𝛠' => 'ρ', + '𝛡' => 'π', + '𝛢' => 'Α', + '𝛣' => 'Β', + '𝛤' => 'Γ', + '𝛥' => 'Δ', + '𝛦' => 'Ε', + '𝛧' => 'Ζ', + '𝛨' => 'Η', + '𝛩' => 'Θ', + '𝛪' => 'Ι', + '𝛫' => 'Κ', + '𝛬' => 'Λ', + '𝛭' => 'Μ', + '𝛮' => 'Ν', + '𝛯' => 'Ξ', + '𝛰' => 'Ο', + '𝛱' => 'Π', + '𝛲' => 'Ρ', + '𝛳' => 'Θ', + '𝛴' => 'Σ', + '𝛵' => 'Τ', + '𝛶' => 'Υ', + '𝛷' => 'Φ', + '𝛸' => 'Χ', + '𝛹' => 'Ψ', + '𝛺' => 'Ω', + '𝛻' => '∇', + '𝛼' => 'α', + '𝛽' => 'β', + '𝛾' => 'γ', + '𝛿' => 'δ', + '𝜀' => 'ε', + '𝜁' => 'ζ', + '𝜂' => 'η', + '𝜃' => 'θ', + '𝜄' => 'ι', + '𝜅' => 'κ', + '𝜆' => 'λ', + '𝜇' => 'μ', + '𝜈' => 'ν', + '𝜉' => 'ξ', + '𝜊' => 'ο', + '𝜋' => 'π', + '𝜌' => 'ρ', + '𝜍' => 'ς', + '𝜎' => 'σ', + '𝜏' => 'τ', + '𝜐' => 'υ', + '𝜑' => 'φ', + '𝜒' => 'χ', + '𝜓' => 'ψ', + '𝜔' => 'ω', + '𝜕' => '∂', + '𝜖' => 'ε', + '𝜗' => 'θ', + '𝜘' => 'κ', + '𝜙' => 'φ', + '𝜚' => 'ρ', + '𝜛' => 'π', + '𝜜' => 'Α', + '𝜝' => 'Β', + '𝜞' => 'Γ', + '𝜟' => 'Δ', + '𝜠' => 'Ε', + '𝜡' => 'Ζ', + '𝜢' => 'Η', + '𝜣' => 'Θ', + '𝜤' => 'Ι', + '𝜥' => 'Κ', + '𝜦' => 'Λ', + '𝜧' => 'Μ', + '𝜨' => 'Ν', + '𝜩' => 'Ξ', + '𝜪' => 'Ο', + '𝜫' => 'Π', + '𝜬' => 'Ρ', + '𝜭' => 'Θ', + '𝜮' => 'Σ', + '𝜯' => 'Τ', + '𝜰' => 'Υ', + '𝜱' => 'Φ', + '𝜲' => 'Χ', + '𝜳' => 'Ψ', + '𝜴' => 'Ω', + '𝜵' => '∇', + '𝜶' => 'α', + '𝜷' => 'β', + '𝜸' => 'γ', + '𝜹' => 'δ', + '𝜺' => 'ε', + '𝜻' => 'ζ', + '𝜼' => 'η', + '𝜽' => 'θ', + '𝜾' => 'ι', + '𝜿' => 'κ', + '𝝀' => 'λ', + '𝝁' => 'μ', + '𝝂' => 'ν', + '𝝃' => 'ξ', + '𝝄' => 'ο', + '𝝅' => 'π', + '𝝆' => 'ρ', + '𝝇' => 'ς', + '𝝈' => 'σ', + '𝝉' => 'τ', + '𝝊' => 'υ', + '𝝋' => 'φ', + '𝝌' => 'χ', + '𝝍' => 'ψ', + '𝝎' => 'ω', + '𝝏' => '∂', + '𝝐' => 'ε', + '𝝑' => 'θ', + '𝝒' => 'κ', + '𝝓' => 'φ', + '𝝔' => 'ρ', + '𝝕' => 'π', + '𝝖' => 'Α', + '𝝗' => 'Β', + '𝝘' => 'Γ', + '𝝙' => 'Δ', + '𝝚' => 'Ε', + '𝝛' => 'Ζ', + '𝝜' => 'Η', + '𝝝' => 'Θ', + '𝝞' => 'Ι', + '𝝟' => 'Κ', + '𝝠' => 'Λ', + '𝝡' => 'Μ', + '𝝢' => 'Ν', + '𝝣' => 'Ξ', + '𝝤' => 'Ο', + '𝝥' => 'Π', + '𝝦' => 'Ρ', + '𝝧' => 'Θ', + '𝝨' => 'Σ', + '𝝩' => 'Τ', + '𝝪' => 'Υ', + '𝝫' => 'Φ', + '𝝬' => 'Χ', + '𝝭' => 'Ψ', + '𝝮' => 'Ω', + '𝝯' => '∇', + '𝝰' => 'α', + '𝝱' => 'β', + '𝝲' => 'γ', + '𝝳' => 'δ', + '𝝴' => 'ε', + '𝝵' => 'ζ', + '𝝶' => 'η', + '𝝷' => 'θ', + '𝝸' => 'ι', + '𝝹' => 'κ', + '𝝺' => 'λ', + '𝝻' => 'μ', + '𝝼' => 'ν', + '𝝽' => 'ξ', + '𝝾' => 'ο', + '𝝿' => 'π', + '𝞀' => 'ρ', + '𝞁' => 'ς', + '𝞂' => 'σ', + '𝞃' => 'τ', + '𝞄' => 'υ', + '𝞅' => 'φ', + '𝞆' => 'χ', + '𝞇' => 'ψ', + '𝞈' => 'ω', + '𝞉' => '∂', + '𝞊' => 'ε', + '𝞋' => 'θ', + '𝞌' => 'κ', + '𝞍' => 'φ', + '𝞎' => 'ρ', + '𝞏' => 'π', + '𝞐' => 'Α', + '𝞑' => 'Β', + '𝞒' => 'Γ', + '𝞓' => 'Δ', + '𝞔' => 'Ε', + '𝞕' => 'Ζ', + '𝞖' => 'Η', + '𝞗' => 'Θ', + '𝞘' => 'Ι', + '𝞙' => 'Κ', + '𝞚' => 'Λ', + '𝞛' => 'Μ', + '𝞜' => 'Ν', + '𝞝' => 'Ξ', + '𝞞' => 'Ο', + '𝞟' => 'Π', + '𝞠' => 'Ρ', + '𝞡' => 'Θ', + '𝞢' => 'Σ', + '𝞣' => 'Τ', + '𝞤' => 'Υ', + '𝞥' => 'Φ', + '𝞦' => 'Χ', + '𝞧' => 'Ψ', + '𝞨' => 'Ω', + '𝞩' => '∇', + '𝞪' => 'α', + '𝞫' => 'β', + '𝞬' => 'γ', + '𝞭' => 'δ', + '𝞮' => 'ε', + '𝞯' => 'ζ', + '𝞰' => 'η', + '𝞱' => 'θ', + '𝞲' => 'ι', + '𝞳' => 'κ', + '𝞴' => 'λ', + '𝞵' => 'μ', + '𝞶' => 'ν', + '𝞷' => 'ξ', + '𝞸' => 'ο', + '𝞹' => 'π', + '𝞺' => 'ρ', + '𝞻' => 'ς', + '𝞼' => 'σ', + '𝞽' => 'τ', + '𝞾' => 'υ', + '𝞿' => 'φ', + '𝟀' => 'χ', + '𝟁' => 'ψ', + '𝟂' => 'ω', + '𝟃' => '∂', + '𝟄' => 'ε', + '𝟅' => 'θ', + '𝟆' => 'κ', + '𝟇' => 'φ', + '𝟈' => 'ρ', + '𝟉' => 'π', + '𝟊' => 'Ϝ', + '𝟋' => 'ϝ', + '𝟎' => '0', + '𝟏' => '1', + '𝟐' => '2', + '𝟑' => '3', + '𝟒' => '4', + '𝟓' => '5', + '𝟔' => '6', + '𝟕' => '7', + '𝟖' => '8', + '𝟗' => '9', + '𝟘' => '0', + '𝟙' => '1', + '𝟚' => '2', + '𝟛' => '3', + '𝟜' => '4', + '𝟝' => '5', + '𝟞' => '6', + '𝟟' => '7', + '𝟠' => '8', + '𝟡' => '9', + '𝟢' => '0', + '𝟣' => '1', + '𝟤' => '2', + '𝟥' => '3', + '𝟦' => '4', + '𝟧' => '5', + '𝟨' => '6', + '𝟩' => '7', + '𝟪' => '8', + '𝟫' => '9', + '𝟬' => '0', + '𝟭' => '1', + '𝟮' => '2', + '𝟯' => '3', + '𝟰' => '4', + '𝟱' => '5', + '𝟲' => '6', + '𝟳' => '7', + '𝟴' => '8', + '𝟵' => '9', + '𝟶' => '0', + '𝟷' => '1', + '𝟸' => '2', + '𝟹' => '3', + '𝟺' => '4', + '𝟻' => '5', + '𝟼' => '6', + '𝟽' => '7', + '𝟾' => '8', + '𝟿' => '9', + '𞸀' => 'ا', + '𞸁' => 'ب', + '𞸂' => 'ج', + '𞸃' => 'د', + '𞸅' => 'و', + '𞸆' => 'ز', + '𞸇' => 'ح', + '𞸈' => 'ط', + '𞸉' => 'ي', + '𞸊' => 'ك', + '𞸋' => 'ل', + '𞸌' => 'م', + '𞸍' => 'ن', + '𞸎' => 'س', + '𞸏' => 'ع', + '𞸐' => 'ف', + '𞸑' => 'ص', + '𞸒' => 'ق', + '𞸓' => 'ر', + '𞸔' => 'ش', + '𞸕' => 'ت', + '𞸖' => 'ث', + '𞸗' => 'خ', + '𞸘' => 'ذ', + '𞸙' => 'ض', + '𞸚' => 'ظ', + '𞸛' => 'غ', + '𞸜' => 'ٮ', + '𞸝' => 'ں', + '𞸞' => 'ڡ', + '𞸟' => 'ٯ', + '𞸡' => 'ب', + '𞸢' => 'ج', + '𞸤' => 'ه', + '𞸧' => 'ح', + '𞸩' => 'ي', + '𞸪' => 'ك', + '𞸫' => 'ل', + '𞸬' => 'م', + '𞸭' => 'ن', + '𞸮' => 'س', + '𞸯' => 'ع', + '𞸰' => 'ف', + '𞸱' => 'ص', + '𞸲' => 'ق', + '𞸴' => 'ش', + '𞸵' => 'ت', + '𞸶' => 'ث', + '𞸷' => 'خ', + '𞸹' => 'ض', + '𞸻' => 'غ', + '𞹂' => 'ج', + '𞹇' => 'ح', + '𞹉' => 'ي', + '𞹋' => 'ل', + '𞹍' => 'ن', + '𞹎' => 'س', + '𞹏' => 'ع', + '𞹑' => 'ص', + '𞹒' => 'ق', + '𞹔' => 'ش', + '𞹗' => 'خ', + '𞹙' => 'ض', + '𞹛' => 'غ', + '𞹝' => 'ں', + '𞹟' => 'ٯ', + '𞹡' => 'ب', + '𞹢' => 'ج', + '𞹤' => 'ه', + '𞹧' => 'ح', + '𞹨' => 'ط', + '𞹩' => 'ي', + '𞹪' => 'ك', + '𞹬' => 'م', + '𞹭' => 'ن', + '𞹮' => 'س', + '𞹯' => 'ع', + '𞹰' => 'ف', + '𞹱' => 'ص', + '𞹲' => 'ق', + '𞹴' => 'ش', + '𞹵' => 'ت', + '𞹶' => 'ث', + '𞹷' => 'خ', + '𞹹' => 'ض', + '𞹺' => 'ظ', + '𞹻' => 'غ', + '𞹼' => 'ٮ', + '𞹾' => 'ڡ', + '𞺀' => 'ا', + '𞺁' => 'ب', + '𞺂' => 'ج', + '𞺃' => 'د', + '𞺄' => 'ه', + '𞺅' => 'و', + '𞺆' => 'ز', + '𞺇' => 'ح', + '𞺈' => 'ط', + '𞺉' => 'ي', + '𞺋' => 'ل', + '𞺌' => 'م', + '𞺍' => 'ن', + '𞺎' => 'س', + '𞺏' => 'ع', + '𞺐' => 'ف', + '𞺑' => 'ص', + '𞺒' => 'ق', + '𞺓' => 'ر', + '𞺔' => 'ش', + '𞺕' => 'ت', + '𞺖' => 'ث', + '𞺗' => 'خ', + '𞺘' => 'ذ', + '𞺙' => 'ض', + '𞺚' => 'ظ', + '𞺛' => 'غ', + '𞺡' => 'ب', + '𞺢' => 'ج', + '𞺣' => 'د', + '𞺥' => 'و', + '𞺦' => 'ز', + '𞺧' => 'ح', + '𞺨' => 'ط', + '𞺩' => 'ي', + '𞺫' => 'ل', + '𞺬' => 'م', + '𞺭' => 'ن', + '𞺮' => 'س', + '𞺯' => 'ع', + '𞺰' => 'ف', + '𞺱' => 'ص', + '𞺲' => 'ق', + '𞺳' => 'ر', + '𞺴' => 'ش', + '𞺵' => 'ت', + '𞺶' => 'ث', + '𞺷' => 'خ', + '𞺸' => 'ذ', + '𞺹' => 'ض', + '𞺺' => 'ظ', + '𞺻' => 'غ', + '🄀' => '0.', + '🄁' => '0,', + '🄂' => '1,', + '🄃' => '2,', + '🄄' => '3,', + '🄅' => '4,', + '🄆' => '5,', + '🄇' => '6,', + '🄈' => '7,', + '🄉' => '8,', + '🄊' => '9,', + '🄐' => '(A)', + '🄑' => '(B)', + '🄒' => '(C)', + '🄓' => '(D)', + '🄔' => '(E)', + '🄕' => '(F)', + '🄖' => '(G)', + '🄗' => '(H)', + '🄘' => '(I)', + '🄙' => '(J)', + '🄚' => '(K)', + '🄛' => '(L)', + '🄜' => '(M)', + '🄝' => '(N)', + '🄞' => '(O)', + '🄟' => '(P)', + '🄠' => '(Q)', + '🄡' => '(R)', + '🄢' => '(S)', + '🄣' => '(T)', + '🄤' => '(U)', + '🄥' => '(V)', + '🄦' => '(W)', + '🄧' => '(X)', + '🄨' => '(Y)', + '🄩' => '(Z)', + '🄪' => '〔S〕', + '🄫' => 'C', + '🄬' => 'R', + '🄭' => 'CD', + '🄮' => 'WZ', + '🄰' => 'A', + '🄱' => 'B', + '🄲' => 'C', + '🄳' => 'D', + '🄴' => 'E', + '🄵' => 'F', + '🄶' => 'G', + '🄷' => 'H', + '🄸' => 'I', + '🄹' => 'J', + '🄺' => 'K', + '🄻' => 'L', + '🄼' => 'M', + '🄽' => 'N', + '🄾' => 'O', + '🄿' => 'P', + '🅀' => 'Q', + '🅁' => 'R', + '🅂' => 'S', + '🅃' => 'T', + '🅄' => 'U', + '🅅' => 'V', + '🅆' => 'W', + '🅇' => 'X', + '🅈' => 'Y', + '🅉' => 'Z', + '🅊' => 'HV', + '🅋' => 'MV', + '🅌' => 'SD', + '🅍' => 'SS', + '🅎' => 'PPV', + '🅏' => 'WC', + '🅪' => 'MC', + '🅫' => 'MD', + '🅬' => 'MR', + '🆐' => 'DJ', + '🈀' => 'ほか', + '🈁' => 'ココ', + '🈂' => 'サ', + '🈐' => '手', + '🈑' => '字', + '🈒' => '双', + '🈓' => 'デ', + '🈔' => '二', + '🈕' => '多', + '🈖' => '解', + '🈗' => '天', + '🈘' => '交', + '🈙' => '映', + '🈚' => '無', + '🈛' => '料', + '🈜' => '前', + '🈝' => '後', + '🈞' => '再', + '🈟' => '新', + '🈠' => '初', + '🈡' => '終', + '🈢' => '生', + '🈣' => '販', + '🈤' => '声', + '🈥' => '吹', + '🈦' => '演', + '🈧' => '投', + '🈨' => '捕', + '🈩' => '一', + '🈪' => '三', + '🈫' => '遊', + '🈬' => '左', + '🈭' => '中', + '🈮' => '右', + '🈯' => '指', + '🈰' => '走', + '🈱' => '打', + '🈲' => '禁', + '🈳' => '空', + '🈴' => '合', + '🈵' => '満', + '🈶' => '有', + '🈷' => '月', + '🈸' => '申', + '🈹' => '割', + '🈺' => '営', + '🈻' => '配', + '🉀' => '〔本〕', + '🉁' => '〔三〕', + '🉂' => '〔二〕', + '🉃' => '〔安〕', + '🉄' => '〔点〕', + '🉅' => '〔打〕', + '🉆' => '〔盗〕', + '🉇' => '〔勝〕', + '🉈' => '〔敗〕', + '🉐' => '得', + '🉑' => '可', + '🯰' => '0', + '🯱' => '1', + '🯲' => '2', + '🯳' => '3', + '🯴' => '4', + '🯵' => '5', + '🯶' => '6', + '🯷' => '7', + '🯸' => '8', + '🯹' => '9', +); diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap.php b/cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap.php new file mode 100644 index 0000000..3608e5c --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Normalizer as p; + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!function_exists('normalizer_is_normalized')) { + function normalizer_is_normalized($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::isNormalized($string, $form); } +} +if (!function_exists('normalizer_normalize')) { + function normalizer_normalize($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::normalize($string, $form); } +} diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php b/cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php new file mode 100644 index 0000000..e36d1a9 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Normalizer as p; + +if (!function_exists('normalizer_is_normalized')) { + function normalizer_is_normalized(?string $string, ?int $form = p\Normalizer::FORM_C): bool { return p\Normalizer::isNormalized((string) $string, (int) $form); } +} +if (!function_exists('normalizer_normalize')) { + function normalizer_normalize(?string $string, ?int $form = p\Normalizer::FORM_C): string|false { return p\Normalizer::normalize((string) $string, (int) $form); } +} diff --git a/cacme/vendor/symfony/polyfill-intl-normalizer/composer.json b/cacme/vendor/symfony/polyfill-intl-normalizer/composer.json new file mode 100644 index 0000000..2c4de2c --- /dev/null +++ b/cacme/vendor/symfony/polyfill-intl-normalizer/composer.json @@ -0,0 +1,39 @@ +{ + "name": "symfony/polyfill-intl-normalizer", + "type": "library", + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "normalizer"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "suggest": { + "ext-intl": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/cacme/vendor/symfony/polyfill-mbstring/LICENSE b/cacme/vendor/symfony/polyfill-mbstring/LICENSE new file mode 100644 index 0000000..6e3afce --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-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/cacme/vendor/symfony/polyfill-mbstring/Mbstring.php b/cacme/vendor/symfony/polyfill-mbstring/Mbstring.php new file mode 100644 index 0000000..2e0b969 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -0,0 +1,947 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Mbstring; + +/** + * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. + * + * Implemented: + * - mb_chr - Returns a specific character from its Unicode code point + * - mb_convert_encoding - Convert character encoding + * - mb_convert_variables - Convert character code in variable(s) + * - mb_decode_mimeheader - Decode string in MIME header field + * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED + * - mb_decode_numericentity - Decode HTML numeric string reference to character + * - mb_encode_numericentity - Encode character to HTML numeric string reference + * - mb_convert_case - Perform case folding on a string + * - mb_detect_encoding - Detect character encoding + * - mb_get_info - Get internal settings of mbstring + * - mb_http_input - Detect HTTP input character encoding + * - mb_http_output - Set/Get HTTP output character encoding + * - mb_internal_encoding - Set/Get internal character encoding + * - mb_list_encodings - Returns an array of all supported encodings + * - mb_ord - Returns the Unicode code point of a character + * - mb_output_handler - Callback function converts character encoding in output buffer + * - mb_scrub - Replaces ill-formed byte sequences with substitute characters + * - mb_strlen - Get string length + * - mb_strpos - Find position of first occurrence of string in a string + * - mb_strrpos - Find position of last occurrence of a string in a string + * - mb_str_split - Convert a string to an array + * - mb_strtolower - Make a string lowercase + * - mb_strtoupper - Make a string uppercase + * - mb_substitute_character - Set/Get substitution character + * - mb_substr - Get part of string + * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive + * - mb_stristr - Finds first occurrence of a string within another, case insensitive + * - mb_strrchr - Finds the last occurrence of a character in a string within another + * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive + * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive + * - mb_strstr - Finds first occurrence of a string within another + * - mb_strwidth - Return width of string + * - mb_substr_count - Count the number of substring occurrences + * + * Not implemented: + * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) + * - mb_ereg_* - Regular expression with multibyte support + * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable + * - mb_preferred_mime_name - Get MIME charset string + * - mb_regex_encoding - Returns current encoding for multibyte regex as string + * - mb_regex_set_options - Set/Get the default options for mbregex functions + * - mb_send_mail - Send encoded mail + * - mb_split - Split multibyte string using regular expression + * - mb_strcut - Get part of string + * - mb_strimwidth - Get truncated string with specified width + * + * @author Nicolas Grekas + * + * @internal + */ +final class Mbstring +{ + public const MB_CASE_FOLD = \PHP_INT_MAX; + + private const SIMPLE_CASE_FOLD = [ + ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], + ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], + ]; + + private static $encodingList = ['ASCII', 'UTF-8']; + private static $language = 'neutral'; + private static $internalEncoding = 'UTF-8'; + + public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) + { + if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { + $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); + } else { + $fromEncoding = self::getEncoding($fromEncoding); + } + + $toEncoding = self::getEncoding($toEncoding); + + if ('BASE64' === $fromEncoding) { + $s = base64_decode($s); + $fromEncoding = $toEncoding; + } + + if ('BASE64' === $toEncoding) { + return base64_encode($s); + } + + if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { + if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { + $fromEncoding = 'Windows-1252'; + } + if ('UTF-8' !== $fromEncoding) { + $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); + } + + return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); + } + + if ('HTML-ENTITIES' === $fromEncoding) { + $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); + $fromEncoding = 'UTF-8'; + } + + return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); + } + + public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) + { + $ok = true; + array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { + if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { + $ok = false; + } + }); + + return $ok ? $fromEncoding : false; + } + + public static function mb_decode_mimeheader($s) + { + return iconv_mime_decode($s, 2, self::$internalEncoding); + } + + public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) + { + trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); + } + + public static function mb_decode_numericentity($s, $convmap, $encoding = null) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return ''; // Instead of null (cf. mb_encode_numericentity). + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $cnt = floor(\count($convmap) / 4) * 4; + + for ($i = 0; $i < $cnt; $i += 4) { + // collector_decode_htmlnumericentity ignores $convmap[$i + 3] + $convmap[$i] += $convmap[$i + 2]; + $convmap[$i + 1] += $convmap[$i + 2]; + } + + $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { + $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; + for ($i = 0; $i < $cnt; $i += 4) { + if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { + return self::mb_chr($c - $convmap[$i + 2]); + } + } + + return $m[0]; + }, $s); + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return null; // Instead of '' (cf. mb_decode_numericentity). + } + + if (null !== $is_hex && !\is_scalar($is_hex)) { + trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); + + return null; + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; + + $cnt = floor(\count($convmap) / 4) * 4; + $i = 0; + $len = \strlen($s); + $result = ''; + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + $c = self::mb_ord($uchr); + + for ($j = 0; $j < $cnt; $j += 4) { + if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { + $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; + $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; + continue 2; + } + } + $result .= $uchr; + } + + if (null === $encoding) { + return $result; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $result); + } + + public static function mb_convert_case($s, $mode, $encoding = null) + { + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + if (\MB_CASE_TITLE == $mode) { + static $titleRegexp = null; + if (null === $titleRegexp) { + $titleRegexp = self::getData('titleCaseRegexp'); + } + $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s); + } else { + if (\MB_CASE_UPPER == $mode) { + static $upper = null; + if (null === $upper) { + $upper = self::getData('upperCase'); + } + $map = $upper; + } else { + if (self::MB_CASE_FOLD === $mode) { + static $caseFolding = null; + if (null === $caseFolding) { + $caseFolding = self::getData('caseFolding'); + } + $s = strtr($s, $caseFolding); + } + + static $lower = null; + if (null === $lower) { + $lower = self::getData('lowerCase'); + } + $map = $lower; + } + + static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; + + $i = 0; + $len = \strlen($s); + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + + if (isset($map[$uchr])) { + $uchr = $map[$uchr]; + $nlen = \strlen($uchr); + + if ($nlen == $ulen) { + $nlen = $i; + do { + $s[--$nlen] = $uchr[--$ulen]; + } while ($ulen); + } else { + $s = substr_replace($s, $uchr, $i - $ulen, $ulen); + $len += $nlen - $ulen; + $i += $nlen - $ulen; + } + } + } + } + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_internal_encoding($encoding = null) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + $normalizedEncoding = self::getEncoding($encoding); + + if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { + self::$internalEncoding = $normalizedEncoding; + + return true; + } + + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); + } + + public static function mb_language($lang = null) + { + if (null === $lang) { + return self::$language; + } + + switch ($normalizedLang = strtolower($lang)) { + case 'uni': + case 'neutral': + self::$language = $normalizedLang; + + return true; + } + + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); + } + + public static function mb_list_encodings() + { + return ['UTF-8']; + } + + public static function mb_encoding_aliases($encoding) + { + switch (strtoupper($encoding)) { + case 'UTF8': + case 'UTF-8': + return ['utf8']; + } + + return false; + } + + public static function mb_check_encoding($var = null, $encoding = null) + { + if (PHP_VERSION_ID < 70200 && \is_array($var)) { + trigger_error('mb_check_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING); + + return null; + } + + if (null === $encoding) { + if (null === $var) { + return false; + } + $encoding = self::$internalEncoding; + } + + if (!\is_array($var)) { + return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); + } + + foreach ($var as $key => $value) { + if (!self::mb_check_encoding($key, $encoding)) { + return false; + } + if (!self::mb_check_encoding($value, $encoding)) { + return false; + } + } + + return true; + + } + + public static function mb_detect_encoding($str, $encodingList = null, $strict = false) + { + if (null === $encodingList) { + $encodingList = self::$encodingList; + } else { + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + } + + foreach ($encodingList as $enc) { + switch ($enc) { + case 'ASCII': + if (!preg_match('/[\x80-\xFF]/', $str)) { + return $enc; + } + break; + + case 'UTF8': + case 'UTF-8': + if (preg_match('//u', $str)) { + return 'UTF-8'; + } + break; + + default: + if (0 === strncmp($enc, 'ISO-8859-', 9)) { + return $enc; + } + } + } + + return false; + } + + public static function mb_detect_order($encodingList = null) + { + if (null === $encodingList) { + return self::$encodingList; + } + + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + + foreach ($encodingList as $enc) { + switch ($enc) { + default: + if (strncmp($enc, 'ISO-8859-', 9)) { + return false; + } + // no break + case 'ASCII': + case 'UTF8': + case 'UTF-8': + } + } + + self::$encodingList = $encodingList; + + return true; + } + + public static function mb_strlen($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return \strlen($s); + } + + return @iconv_strlen($s, $encoding); + } + + public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strpos($haystack, $needle, $offset); + } + + $needle = (string) $needle; + if ('' === $needle) { + if (80000 > \PHP_VERSION_ID) { + trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING); + + return false; + } + + return 0; + } + + return iconv_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strrpos($haystack, $needle, $offset); + } + + if ($offset != (int) $offset) { + $offset = 0; + } elseif ($offset = (int) $offset) { + if ($offset < 0) { + if (0 > $offset += self::mb_strlen($needle)) { + $haystack = self::mb_substr($haystack, 0, $offset, $encoding); + } + $offset = 0; + } else { + $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); + } + } + + $pos = '' !== $needle || 80000 > \PHP_VERSION_ID + ? iconv_strrpos($haystack, $needle, $encoding) + : self::mb_strlen($haystack, $encoding); + + return false !== $pos ? $offset + $pos : false; + } + + public static function mb_str_split($string, $split_length = 1, $encoding = null) + { + if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { + trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); + + return null; + } + + if (1 > $split_length = (int) $split_length) { + if (80000 > \PHP_VERSION_ID) { + trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); + + return false; + } + + throw new \ValueError('Argument #2 ($length) must be greater than 0'); + } + + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + + if ('UTF-8' === $encoding = self::getEncoding($encoding)) { + $rx = '/('; + while (65535 < $split_length) { + $rx .= '.{65535}'; + $split_length -= 65535; + } + $rx .= '.{'.$split_length.'})/us'; + + return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + } + + $result = []; + $length = mb_strlen($string, $encoding); + + for ($i = 0; $i < $length; $i += $split_length) { + $result[] = mb_substr($string, $i, $split_length, $encoding); + } + + return $result; + } + + public static function mb_strtolower($s, $encoding = null) + { + return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); + } + + public static function mb_strtoupper($s, $encoding = null) + { + return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); + } + + public static function mb_substitute_character($c = null) + { + if (null === $c) { + return 'none'; + } + if (0 === strcasecmp($c, 'none')) { + return true; + } + if (80000 > \PHP_VERSION_ID) { + return false; + } + if (\is_int($c) || 'long' === $c || 'entity' === $c) { + return false; + } + + throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint'); + } + + public static function mb_substr($s, $start, $length = null, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return (string) substr($s, $start, null === $length ? 2147483647 : $length); + } + + if ($start < 0) { + $start = iconv_strlen($s, $encoding) + $start; + if ($start < 0) { + $start = 0; + } + } + + if (null === $length) { + $length = 2147483647; + } elseif ($length < 0) { + $length = iconv_strlen($s, $encoding) + $length - $start; + if ($length < 0) { + return ''; + } + } + + return (string) iconv_substr($s, $start, $length, $encoding); + } + + public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) + { + [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [ + self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), + self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding), + ]); + + return self::mb_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) + { + $pos = self::mb_stripos($haystack, $needle, 0, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + $pos = strrpos($haystack, $needle); + } else { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = iconv_strrpos($haystack, $needle, $encoding); + } + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) + { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = self::mb_strripos($haystack, $needle, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) + { + $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding); + $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding); + + $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack); + $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle); + + return self::mb_strrpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) + { + $pos = strpos($haystack, $needle); + if (false === $pos) { + return false; + } + if ($part) { + return substr($haystack, 0, $pos); + } + + return substr($haystack, $pos); + } + + public static function mb_get_info($type = 'all') + { + $info = [ + 'internal_encoding' => self::$internalEncoding, + 'http_output' => 'pass', + 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', + 'func_overload' => 0, + 'func_overload_list' => 'no overload', + 'mail_charset' => 'UTF-8', + 'mail_header_encoding' => 'BASE64', + 'mail_body_encoding' => 'BASE64', + 'illegal_chars' => 0, + 'encoding_translation' => 'Off', + 'language' => self::$language, + 'detect_order' => self::$encodingList, + 'substitute_character' => 'none', + 'strict_detection' => 'Off', + ]; + + if ('all' === $type) { + return $info; + } + if (isset($info[$type])) { + return $info[$type]; + } + + return false; + } + + public static function mb_http_input($type = '') + { + return false; + } + + public static function mb_http_output($encoding = null) + { + return null !== $encoding ? 'pass' === $encoding : 'pass'; + } + + public static function mb_strwidth($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + + if ('UTF-8' !== $encoding) { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); + + return ($wide << 1) + iconv_strlen($s, 'UTF-8'); + } + + public static function mb_substr_count($haystack, $needle, $encoding = null) + { + return substr_count($haystack, $needle); + } + + public static function mb_output_handler($contents, $status) + { + return $contents; + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } + + public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, string $encoding = null): string + { + if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { + throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); + } + + if (null === $encoding) { + $encoding = self::mb_internal_encoding(); + } + + try { + $validEncoding = @self::mb_check_encoding('', $encoding); + } catch (\ValueError $e) { + throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding)); + } + + // BC for PHP 7.3 and lower + if (!$validEncoding) { + throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding)); + } + + if (self::mb_strlen($pad_string, $encoding) <= 0) { + throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); + } + + $paddingRequired = $length - self::mb_strlen($string, $encoding); + + if ($paddingRequired < 1) { + return $string; + } + + switch ($pad_type) { + case \STR_PAD_LEFT: + return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string; + case \STR_PAD_RIGHT: + return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding); + default: + $leftPaddingLength = floor($paddingRequired / 2); + $rightPaddingLength = $paddingRequired - $leftPaddingLength; + + return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding); + } + } + + private static function getSubpart($pos, $part, $haystack, $encoding) + { + if (false === $pos) { + return false; + } + if ($part) { + return self::mb_substr($haystack, 0, $pos, $encoding); + } + + return self::mb_substr($haystack, $pos, null, $encoding); + } + + private static function html_encoding_callback(array $m) + { + $i = 1; + $entities = ''; + $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); + + while (isset($m[$i])) { + if (0x80 > $m[$i]) { + $entities .= \chr($m[$i++]); + continue; + } + if (0xF0 <= $m[$i]) { + $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } elseif (0xE0 <= $m[$i]) { + $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } else { + $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; + } + + $entities .= '&#'.$c.';'; + } + + return $entities; + } + + private static function title_case(array $s) + { + return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); + } + + private static function getData($file) + { + if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { + return require $file; + } + + return false; + } + + private static function getEncoding($encoding) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + if ('UTF-8' === $encoding) { + return 'UTF-8'; + } + + $encoding = strtoupper($encoding); + + if ('8BIT' === $encoding || 'BINARY' === $encoding) { + return 'CP850'; + } + + if ('UTF8' === $encoding) { + return 'UTF-8'; + } + + return $encoding; + } +} diff --git a/cacme/vendor/symfony/polyfill-mbstring/README.md b/cacme/vendor/symfony/polyfill-mbstring/README.md new file mode 100644 index 0000000..478b40d --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/README.md @@ -0,0 +1,13 @@ +Symfony Polyfill / Mbstring +=========================== + +This component provides a partial, native PHP implementation for the +[Mbstring](https://php.net/mbstring) extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php b/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php new file mode 100644 index 0000000..512bba0 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php @@ -0,0 +1,119 @@ + 'i̇', + 'µ' => 'μ', + 'ſ' => 's', + 'ͅ' => 'ι', + 'ς' => 'σ', + 'ϐ' => 'β', + 'ϑ' => 'θ', + 'ϕ' => 'φ', + 'ϖ' => 'π', + 'ϰ' => 'κ', + 'ϱ' => 'ρ', + 'ϵ' => 'ε', + 'ẛ' => 'ṡ', + 'ι' => 'ι', + 'ß' => 'ss', + 'ʼn' => 'ʼn', + 'ǰ' => 'ǰ', + 'ΐ' => 'ΐ', + 'ΰ' => 'ΰ', + 'և' => 'եւ', + 'ẖ' => 'ẖ', + 'ẗ' => 'ẗ', + 'ẘ' => 'ẘ', + 'ẙ' => 'ẙ', + 'ẚ' => 'aʾ', + 'ẞ' => 'ss', + 'ὐ' => 'ὐ', + 'ὒ' => 'ὒ', + 'ὔ' => 'ὔ', + 'ὖ' => 'ὖ', + 'ᾀ' => 'ἀι', + 'ᾁ' => 'ἁι', + 'ᾂ' => 'ἂι', + 'ᾃ' => 'ἃι', + 'ᾄ' => 'ἄι', + 'ᾅ' => 'ἅι', + 'ᾆ' => 'ἆι', + 'ᾇ' => 'ἇι', + 'ᾈ' => 'ἀι', + 'ᾉ' => 'ἁι', + 'ᾊ' => 'ἂι', + 'ᾋ' => 'ἃι', + 'ᾌ' => 'ἄι', + 'ᾍ' => 'ἅι', + 'ᾎ' => 'ἆι', + 'ᾏ' => 'ἇι', + 'ᾐ' => 'ἠι', + 'ᾑ' => 'ἡι', + 'ᾒ' => 'ἢι', + 'ᾓ' => 'ἣι', + 'ᾔ' => 'ἤι', + 'ᾕ' => 'ἥι', + 'ᾖ' => 'ἦι', + 'ᾗ' => 'ἧι', + 'ᾘ' => 'ἠι', + 'ᾙ' => 'ἡι', + 'ᾚ' => 'ἢι', + 'ᾛ' => 'ἣι', + 'ᾜ' => 'ἤι', + 'ᾝ' => 'ἥι', + 'ᾞ' => 'ἦι', + 'ᾟ' => 'ἧι', + 'ᾠ' => 'ὠι', + 'ᾡ' => 'ὡι', + 'ᾢ' => 'ὢι', + 'ᾣ' => 'ὣι', + 'ᾤ' => 'ὤι', + 'ᾥ' => 'ὥι', + 'ᾦ' => 'ὦι', + 'ᾧ' => 'ὧι', + 'ᾨ' => 'ὠι', + 'ᾩ' => 'ὡι', + 'ᾪ' => 'ὢι', + 'ᾫ' => 'ὣι', + 'ᾬ' => 'ὤι', + 'ᾭ' => 'ὥι', + 'ᾮ' => 'ὦι', + 'ᾯ' => 'ὧι', + 'ᾲ' => 'ὰι', + 'ᾳ' => 'αι', + 'ᾴ' => 'άι', + 'ᾶ' => 'ᾶ', + 'ᾷ' => 'ᾶι', + 'ᾼ' => 'αι', + 'ῂ' => 'ὴι', + 'ῃ' => 'ηι', + 'ῄ' => 'ήι', + 'ῆ' => 'ῆ', + 'ῇ' => 'ῆι', + 'ῌ' => 'ηι', + 'ῒ' => 'ῒ', + 'ῖ' => 'ῖ', + 'ῗ' => 'ῗ', + 'ῢ' => 'ῢ', + 'ῤ' => 'ῤ', + 'ῦ' => 'ῦ', + 'ῧ' => 'ῧ', + 'ῲ' => 'ὼι', + 'ῳ' => 'ωι', + 'ῴ' => 'ώι', + 'ῶ' => 'ῶ', + 'ῷ' => 'ῶι', + 'ῼ' => 'ωι', + 'ff' => 'ff', + 'fi' => 'fi', + 'fl' => 'fl', + 'ffi' => 'ffi', + 'ffl' => 'ffl', + 'ſt' => 'st', + 'st' => 'st', + 'ﬓ' => 'մն', + 'ﬔ' => 'մե', + 'ﬕ' => 'մի', + 'ﬖ' => 'վն', + 'ﬗ' => 'մխ', +]; diff --git a/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php new file mode 100644 index 0000000..fac60b0 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php @@ -0,0 +1,1397 @@ + 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + 'À' => 'à', + 'Á' => 'á', + 'Â' => 'â', + 'Ã' => 'ã', + 'Ä' => 'ä', + 'Å' => 'å', + 'Æ' => 'æ', + 'Ç' => 'ç', + 'È' => 'è', + 'É' => 'é', + 'Ê' => 'ê', + 'Ë' => 'ë', + 'Ì' => 'ì', + 'Í' => 'í', + 'Î' => 'î', + 'Ï' => 'ï', + 'Ð' => 'ð', + 'Ñ' => 'ñ', + 'Ò' => 'ò', + 'Ó' => 'ó', + 'Ô' => 'ô', + 'Õ' => 'õ', + 'Ö' => 'ö', + 'Ø' => 'ø', + 'Ù' => 'ù', + 'Ú' => 'ú', + 'Û' => 'û', + 'Ü' => 'ü', + 'Ý' => 'ý', + 'Þ' => 'þ', + 'Ā' => 'ā', + 'Ă' => 'ă', + 'Ą' => 'ą', + 'Ć' => 'ć', + 'Ĉ' => 'ĉ', + 'Ċ' => 'ċ', + 'Č' => 'č', + 'Ď' => 'ď', + 'Đ' => 'đ', + 'Ē' => 'ē', + 'Ĕ' => 'ĕ', + 'Ė' => 'ė', + 'Ę' => 'ę', + 'Ě' => 'ě', + 'Ĝ' => 'ĝ', + 'Ğ' => 'ğ', + 'Ġ' => 'ġ', + 'Ģ' => 'ģ', + 'Ĥ' => 'ĥ', + 'Ħ' => 'ħ', + 'Ĩ' => 'ĩ', + 'Ī' => 'ī', + 'Ĭ' => 'ĭ', + 'Į' => 'į', + 'İ' => 'i̇', + 'IJ' => 'ij', + 'Ĵ' => 'ĵ', + 'Ķ' => 'ķ', + 'Ĺ' => 'ĺ', + 'Ļ' => 'ļ', + 'Ľ' => 'ľ', + 'Ŀ' => 'ŀ', + 'Ł' => 'ł', + 'Ń' => 'ń', + 'Ņ' => 'ņ', + 'Ň' => 'ň', + 'Ŋ' => 'ŋ', + 'Ō' => 'ō', + 'Ŏ' => 'ŏ', + 'Ő' => 'ő', + 'Œ' => 'œ', + 'Ŕ' => 'ŕ', + 'Ŗ' => 'ŗ', + 'Ř' => 'ř', + 'Ś' => 'ś', + 'Ŝ' => 'ŝ', + 'Ş' => 'ş', + 'Š' => 'š', + 'Ţ' => 'ţ', + 'Ť' => 'ť', + 'Ŧ' => 'ŧ', + 'Ũ' => 'ũ', + 'Ū' => 'ū', + 'Ŭ' => 'ŭ', + 'Ů' => 'ů', + 'Ű' => 'ű', + 'Ų' => 'ų', + 'Ŵ' => 'ŵ', + 'Ŷ' => 'ŷ', + 'Ÿ' => 'ÿ', + 'Ź' => 'ź', + 'Ż' => 'ż', + 'Ž' => 'ž', + 'Ɓ' => 'ɓ', + 'Ƃ' => 'ƃ', + 'Ƅ' => 'ƅ', + 'Ɔ' => 'ɔ', + 'Ƈ' => 'ƈ', + 'Ɖ' => 'ɖ', + 'Ɗ' => 'ɗ', + 'Ƌ' => 'ƌ', + 'Ǝ' => 'ǝ', + 'Ə' => 'ə', + 'Ɛ' => 'ɛ', + 'Ƒ' => 'ƒ', + 'Ɠ' => 'ɠ', + 'Ɣ' => 'ɣ', + 'Ɩ' => 'ɩ', + 'Ɨ' => 'ɨ', + 'Ƙ' => 'ƙ', + 'Ɯ' => 'ɯ', + 'Ɲ' => 'ɲ', + 'Ɵ' => 'ɵ', + 'Ơ' => 'ơ', + 'Ƣ' => 'ƣ', + 'Ƥ' => 'ƥ', + 'Ʀ' => 'ʀ', + 'Ƨ' => 'ƨ', + 'Ʃ' => 'ʃ', + 'Ƭ' => 'ƭ', + 'Ʈ' => 'ʈ', + 'Ư' => 'ư', + 'Ʊ' => 'ʊ', + 'Ʋ' => 'ʋ', + 'Ƴ' => 'ƴ', + 'Ƶ' => 'ƶ', + 'Ʒ' => 'ʒ', + 'Ƹ' => 'ƹ', + 'Ƽ' => 'ƽ', + 'DŽ' => 'dž', + 'Dž' => 'dž', + 'LJ' => 'lj', + 'Lj' => 'lj', + 'NJ' => 'nj', + 'Nj' => 'nj', + 'Ǎ' => 'ǎ', + 'Ǐ' => 'ǐ', + 'Ǒ' => 'ǒ', + 'Ǔ' => 'ǔ', + 'Ǖ' => 'ǖ', + 'Ǘ' => 'ǘ', + 'Ǚ' => 'ǚ', + 'Ǜ' => 'ǜ', + 'Ǟ' => 'ǟ', + 'Ǡ' => 'ǡ', + 'Ǣ' => 'ǣ', + 'Ǥ' => 'ǥ', + 'Ǧ' => 'ǧ', + 'Ǩ' => 'ǩ', + 'Ǫ' => 'ǫ', + 'Ǭ' => 'ǭ', + 'Ǯ' => 'ǯ', + 'DZ' => 'dz', + 'Dz' => 'dz', + 'Ǵ' => 'ǵ', + 'Ƕ' => 'ƕ', + 'Ƿ' => 'ƿ', + 'Ǹ' => 'ǹ', + 'Ǻ' => 'ǻ', + 'Ǽ' => 'ǽ', + 'Ǿ' => 'ǿ', + 'Ȁ' => 'ȁ', + 'Ȃ' => 'ȃ', + 'Ȅ' => 'ȅ', + 'Ȇ' => 'ȇ', + 'Ȉ' => 'ȉ', + 'Ȋ' => 'ȋ', + 'Ȍ' => 'ȍ', + 'Ȏ' => 'ȏ', + 'Ȑ' => 'ȑ', + 'Ȓ' => 'ȓ', + 'Ȕ' => 'ȕ', + 'Ȗ' => 'ȗ', + 'Ș' => 'ș', + 'Ț' => 'ț', + 'Ȝ' => 'ȝ', + 'Ȟ' => 'ȟ', + 'Ƞ' => 'ƞ', + 'Ȣ' => 'ȣ', + 'Ȥ' => 'ȥ', + 'Ȧ' => 'ȧ', + 'Ȩ' => 'ȩ', + 'Ȫ' => 'ȫ', + 'Ȭ' => 'ȭ', + 'Ȯ' => 'ȯ', + 'Ȱ' => 'ȱ', + 'Ȳ' => 'ȳ', + 'Ⱥ' => 'ⱥ', + 'Ȼ' => 'ȼ', + 'Ƚ' => 'ƚ', + 'Ⱦ' => 'ⱦ', + 'Ɂ' => 'ɂ', + 'Ƀ' => 'ƀ', + 'Ʉ' => 'ʉ', + 'Ʌ' => 'ʌ', + 'Ɇ' => 'ɇ', + 'Ɉ' => 'ɉ', + 'Ɋ' => 'ɋ', + 'Ɍ' => 'ɍ', + 'Ɏ' => 'ɏ', + 'Ͱ' => 'ͱ', + 'Ͳ' => 'ͳ', + 'Ͷ' => 'ͷ', + 'Ϳ' => 'ϳ', + 'Ά' => 'ά', + 'Έ' => 'έ', + 'Ή' => 'ή', + 'Ί' => 'ί', + 'Ό' => 'ό', + 'Ύ' => 'ύ', + 'Ώ' => 'ώ', + 'Α' => 'α', + 'Β' => 'β', + 'Γ' => 'γ', + 'Δ' => 'δ', + 'Ε' => 'ε', + 'Ζ' => 'ζ', + 'Η' => 'η', + 'Θ' => 'θ', + 'Ι' => 'ι', + 'Κ' => 'κ', + 'Λ' => 'λ', + 'Μ' => 'μ', + 'Ν' => 'ν', + 'Ξ' => 'ξ', + 'Ο' => 'ο', + 'Π' => 'π', + 'Ρ' => 'ρ', + 'Σ' => 'σ', + 'Τ' => 'τ', + 'Υ' => 'υ', + 'Φ' => 'φ', + 'Χ' => 'χ', + 'Ψ' => 'ψ', + 'Ω' => 'ω', + 'Ϊ' => 'ϊ', + 'Ϋ' => 'ϋ', + 'Ϗ' => 'ϗ', + 'Ϙ' => 'ϙ', + 'Ϛ' => 'ϛ', + 'Ϝ' => 'ϝ', + 'Ϟ' => 'ϟ', + 'Ϡ' => 'ϡ', + 'Ϣ' => 'ϣ', + 'Ϥ' => 'ϥ', + 'Ϧ' => 'ϧ', + 'Ϩ' => 'ϩ', + 'Ϫ' => 'ϫ', + 'Ϭ' => 'ϭ', + 'Ϯ' => 'ϯ', + 'ϴ' => 'θ', + 'Ϸ' => 'ϸ', + 'Ϲ' => 'ϲ', + 'Ϻ' => 'ϻ', + 'Ͻ' => 'ͻ', + 'Ͼ' => 'ͼ', + 'Ͽ' => 'ͽ', + 'Ѐ' => 'ѐ', + 'Ё' => 'ё', + 'Ђ' => 'ђ', + 'Ѓ' => 'ѓ', + 'Є' => 'є', + 'Ѕ' => 'ѕ', + 'І' => 'і', + 'Ї' => 'ї', + 'Ј' => 'ј', + 'Љ' => 'љ', + 'Њ' => 'њ', + 'Ћ' => 'ћ', + 'Ќ' => 'ќ', + 'Ѝ' => 'ѝ', + 'Ў' => 'ў', + 'Џ' => 'џ', + 'А' => 'а', + 'Б' => 'б', + 'В' => 'в', + 'Г' => 'г', + 'Д' => 'д', + 'Е' => 'е', + 'Ж' => 'ж', + 'З' => 'з', + 'И' => 'и', + 'Й' => 'й', + 'К' => 'к', + 'Л' => 'л', + 'М' => 'м', + 'Н' => 'н', + 'О' => 'о', + 'П' => 'п', + 'Р' => 'р', + 'С' => 'с', + 'Т' => 'т', + 'У' => 'у', + 'Ф' => 'ф', + 'Х' => 'х', + 'Ц' => 'ц', + 'Ч' => 'ч', + 'Ш' => 'ш', + 'Щ' => 'щ', + 'Ъ' => 'ъ', + 'Ы' => 'ы', + 'Ь' => 'ь', + 'Э' => 'э', + 'Ю' => 'ю', + 'Я' => 'я', + 'Ѡ' => 'ѡ', + 'Ѣ' => 'ѣ', + 'Ѥ' => 'ѥ', + 'Ѧ' => 'ѧ', + 'Ѩ' => 'ѩ', + 'Ѫ' => 'ѫ', + 'Ѭ' => 'ѭ', + 'Ѯ' => 'ѯ', + 'Ѱ' => 'ѱ', + 'Ѳ' => 'ѳ', + 'Ѵ' => 'ѵ', + 'Ѷ' => 'ѷ', + 'Ѹ' => 'ѹ', + 'Ѻ' => 'ѻ', + 'Ѽ' => 'ѽ', + 'Ѿ' => 'ѿ', + 'Ҁ' => 'ҁ', + 'Ҋ' => 'ҋ', + 'Ҍ' => 'ҍ', + 'Ҏ' => 'ҏ', + 'Ґ' => 'ґ', + 'Ғ' => 'ғ', + 'Ҕ' => 'ҕ', + 'Җ' => 'җ', + 'Ҙ' => 'ҙ', + 'Қ' => 'қ', + 'Ҝ' => 'ҝ', + 'Ҟ' => 'ҟ', + 'Ҡ' => 'ҡ', + 'Ң' => 'ң', + 'Ҥ' => 'ҥ', + 'Ҧ' => 'ҧ', + 'Ҩ' => 'ҩ', + 'Ҫ' => 'ҫ', + 'Ҭ' => 'ҭ', + 'Ү' => 'ү', + 'Ұ' => 'ұ', + 'Ҳ' => 'ҳ', + 'Ҵ' => 'ҵ', + 'Ҷ' => 'ҷ', + 'Ҹ' => 'ҹ', + 'Һ' => 'һ', + 'Ҽ' => 'ҽ', + 'Ҿ' => 'ҿ', + 'Ӏ' => 'ӏ', + 'Ӂ' => 'ӂ', + 'Ӄ' => 'ӄ', + 'Ӆ' => 'ӆ', + 'Ӈ' => 'ӈ', + 'Ӊ' => 'ӊ', + 'Ӌ' => 'ӌ', + 'Ӎ' => 'ӎ', + 'Ӑ' => 'ӑ', + 'Ӓ' => 'ӓ', + 'Ӕ' => 'ӕ', + 'Ӗ' => 'ӗ', + 'Ә' => 'ә', + 'Ӛ' => 'ӛ', + 'Ӝ' => 'ӝ', + 'Ӟ' => 'ӟ', + 'Ӡ' => 'ӡ', + 'Ӣ' => 'ӣ', + 'Ӥ' => 'ӥ', + 'Ӧ' => 'ӧ', + 'Ө' => 'ө', + 'Ӫ' => 'ӫ', + 'Ӭ' => 'ӭ', + 'Ӯ' => 'ӯ', + 'Ӱ' => 'ӱ', + 'Ӳ' => 'ӳ', + 'Ӵ' => 'ӵ', + 'Ӷ' => 'ӷ', + 'Ӹ' => 'ӹ', + 'Ӻ' => 'ӻ', + 'Ӽ' => 'ӽ', + 'Ӿ' => 'ӿ', + 'Ԁ' => 'ԁ', + 'Ԃ' => 'ԃ', + 'Ԅ' => 'ԅ', + 'Ԇ' => 'ԇ', + 'Ԉ' => 'ԉ', + 'Ԋ' => 'ԋ', + 'Ԍ' => 'ԍ', + 'Ԏ' => 'ԏ', + 'Ԑ' => 'ԑ', + 'Ԓ' => 'ԓ', + 'Ԕ' => 'ԕ', + 'Ԗ' => 'ԗ', + 'Ԙ' => 'ԙ', + 'Ԛ' => 'ԛ', + 'Ԝ' => 'ԝ', + 'Ԟ' => 'ԟ', + 'Ԡ' => 'ԡ', + 'Ԣ' => 'ԣ', + 'Ԥ' => 'ԥ', + 'Ԧ' => 'ԧ', + 'Ԩ' => 'ԩ', + 'Ԫ' => 'ԫ', + 'Ԭ' => 'ԭ', + 'Ԯ' => 'ԯ', + 'Ա' => 'ա', + 'Բ' => 'բ', + 'Գ' => 'գ', + 'Դ' => 'դ', + 'Ե' => 'ե', + 'Զ' => 'զ', + 'Է' => 'է', + 'Ը' => 'ը', + 'Թ' => 'թ', + 'Ժ' => 'ժ', + 'Ի' => 'ի', + 'Լ' => 'լ', + 'Խ' => 'խ', + 'Ծ' => 'ծ', + 'Կ' => 'կ', + 'Հ' => 'հ', + 'Ձ' => 'ձ', + 'Ղ' => 'ղ', + 'Ճ' => 'ճ', + 'Մ' => 'մ', + 'Յ' => 'յ', + 'Ն' => 'ն', + 'Շ' => 'շ', + 'Ո' => 'ո', + 'Չ' => 'չ', + 'Պ' => 'պ', + 'Ջ' => 'ջ', + 'Ռ' => 'ռ', + 'Ս' => 'ս', + 'Վ' => 'վ', + 'Տ' => 'տ', + 'Ր' => 'ր', + 'Ց' => 'ց', + 'Ւ' => 'ւ', + 'Փ' => 'փ', + 'Ք' => 'ք', + 'Օ' => 'օ', + 'Ֆ' => 'ֆ', + 'Ⴀ' => 'ⴀ', + 'Ⴁ' => 'ⴁ', + 'Ⴂ' => 'ⴂ', + 'Ⴃ' => 'ⴃ', + 'Ⴄ' => 'ⴄ', + 'Ⴅ' => 'ⴅ', + 'Ⴆ' => 'ⴆ', + 'Ⴇ' => 'ⴇ', + 'Ⴈ' => 'ⴈ', + 'Ⴉ' => 'ⴉ', + 'Ⴊ' => 'ⴊ', + 'Ⴋ' => 'ⴋ', + 'Ⴌ' => 'ⴌ', + 'Ⴍ' => 'ⴍ', + 'Ⴎ' => 'ⴎ', + 'Ⴏ' => 'ⴏ', + 'Ⴐ' => 'ⴐ', + 'Ⴑ' => 'ⴑ', + 'Ⴒ' => 'ⴒ', + 'Ⴓ' => 'ⴓ', + 'Ⴔ' => 'ⴔ', + 'Ⴕ' => 'ⴕ', + 'Ⴖ' => 'ⴖ', + 'Ⴗ' => 'ⴗ', + 'Ⴘ' => 'ⴘ', + 'Ⴙ' => 'ⴙ', + 'Ⴚ' => 'ⴚ', + 'Ⴛ' => 'ⴛ', + 'Ⴜ' => 'ⴜ', + 'Ⴝ' => 'ⴝ', + 'Ⴞ' => 'ⴞ', + 'Ⴟ' => 'ⴟ', + 'Ⴠ' => 'ⴠ', + 'Ⴡ' => 'ⴡ', + 'Ⴢ' => 'ⴢ', + 'Ⴣ' => 'ⴣ', + 'Ⴤ' => 'ⴤ', + 'Ⴥ' => 'ⴥ', + 'Ⴧ' => 'ⴧ', + 'Ⴭ' => 'ⴭ', + 'Ꭰ' => 'ꭰ', + 'Ꭱ' => 'ꭱ', + 'Ꭲ' => 'ꭲ', + 'Ꭳ' => 'ꭳ', + 'Ꭴ' => 'ꭴ', + 'Ꭵ' => 'ꭵ', + 'Ꭶ' => 'ꭶ', + 'Ꭷ' => 'ꭷ', + 'Ꭸ' => 'ꭸ', + 'Ꭹ' => 'ꭹ', + 'Ꭺ' => 'ꭺ', + 'Ꭻ' => 'ꭻ', + 'Ꭼ' => 'ꭼ', + 'Ꭽ' => 'ꭽ', + 'Ꭾ' => 'ꭾ', + 'Ꭿ' => 'ꭿ', + 'Ꮀ' => 'ꮀ', + 'Ꮁ' => 'ꮁ', + 'Ꮂ' => 'ꮂ', + 'Ꮃ' => 'ꮃ', + 'Ꮄ' => 'ꮄ', + 'Ꮅ' => 'ꮅ', + 'Ꮆ' => 'ꮆ', + 'Ꮇ' => 'ꮇ', + 'Ꮈ' => 'ꮈ', + 'Ꮉ' => 'ꮉ', + 'Ꮊ' => 'ꮊ', + 'Ꮋ' => 'ꮋ', + 'Ꮌ' => 'ꮌ', + 'Ꮍ' => 'ꮍ', + 'Ꮎ' => 'ꮎ', + 'Ꮏ' => 'ꮏ', + 'Ꮐ' => 'ꮐ', + 'Ꮑ' => 'ꮑ', + 'Ꮒ' => 'ꮒ', + 'Ꮓ' => 'ꮓ', + 'Ꮔ' => 'ꮔ', + 'Ꮕ' => 'ꮕ', + 'Ꮖ' => 'ꮖ', + 'Ꮗ' => 'ꮗ', + 'Ꮘ' => 'ꮘ', + 'Ꮙ' => 'ꮙ', + 'Ꮚ' => 'ꮚ', + 'Ꮛ' => 'ꮛ', + 'Ꮜ' => 'ꮜ', + 'Ꮝ' => 'ꮝ', + 'Ꮞ' => 'ꮞ', + 'Ꮟ' => 'ꮟ', + 'Ꮠ' => 'ꮠ', + 'Ꮡ' => 'ꮡ', + 'Ꮢ' => 'ꮢ', + 'Ꮣ' => 'ꮣ', + 'Ꮤ' => 'ꮤ', + 'Ꮥ' => 'ꮥ', + 'Ꮦ' => 'ꮦ', + 'Ꮧ' => 'ꮧ', + 'Ꮨ' => 'ꮨ', + 'Ꮩ' => 'ꮩ', + 'Ꮪ' => 'ꮪ', + 'Ꮫ' => 'ꮫ', + 'Ꮬ' => 'ꮬ', + 'Ꮭ' => 'ꮭ', + 'Ꮮ' => 'ꮮ', + 'Ꮯ' => 'ꮯ', + 'Ꮰ' => 'ꮰ', + 'Ꮱ' => 'ꮱ', + 'Ꮲ' => 'ꮲ', + 'Ꮳ' => 'ꮳ', + 'Ꮴ' => 'ꮴ', + 'Ꮵ' => 'ꮵ', + 'Ꮶ' => 'ꮶ', + 'Ꮷ' => 'ꮷ', + 'Ꮸ' => 'ꮸ', + 'Ꮹ' => 'ꮹ', + 'Ꮺ' => 'ꮺ', + 'Ꮻ' => 'ꮻ', + 'Ꮼ' => 'ꮼ', + 'Ꮽ' => 'ꮽ', + 'Ꮾ' => 'ꮾ', + 'Ꮿ' => 'ꮿ', + 'Ᏸ' => 'ᏸ', + 'Ᏹ' => 'ᏹ', + 'Ᏺ' => 'ᏺ', + 'Ᏻ' => 'ᏻ', + 'Ᏼ' => 'ᏼ', + 'Ᏽ' => 'ᏽ', + 'Ა' => 'ა', + 'Ბ' => 'ბ', + 'Გ' => 'გ', + 'Დ' => 'დ', + 'Ე' => 'ე', + 'Ვ' => 'ვ', + 'Ზ' => 'ზ', + 'Თ' => 'თ', + 'Ი' => 'ი', + 'Კ' => 'კ', + 'Ლ' => 'ლ', + 'Მ' => 'მ', + 'Ნ' => 'ნ', + 'Ო' => 'ო', + 'Პ' => 'პ', + 'Ჟ' => 'ჟ', + 'Რ' => 'რ', + 'Ს' => 'ს', + 'Ტ' => 'ტ', + 'Უ' => 'უ', + 'Ფ' => 'ფ', + 'Ქ' => 'ქ', + 'Ღ' => 'ღ', + 'Ყ' => 'ყ', + 'Შ' => 'შ', + 'Ჩ' => 'ჩ', + 'Ც' => 'ც', + 'Ძ' => 'ძ', + 'Წ' => 'წ', + 'Ჭ' => 'ჭ', + 'Ხ' => 'ხ', + 'Ჯ' => 'ჯ', + 'Ჰ' => 'ჰ', + 'Ჱ' => 'ჱ', + 'Ჲ' => 'ჲ', + 'Ჳ' => 'ჳ', + 'Ჴ' => 'ჴ', + 'Ჵ' => 'ჵ', + 'Ჶ' => 'ჶ', + 'Ჷ' => 'ჷ', + 'Ჸ' => 'ჸ', + 'Ჹ' => 'ჹ', + 'Ჺ' => 'ჺ', + 'Ჽ' => 'ჽ', + 'Ჾ' => 'ჾ', + 'Ჿ' => 'ჿ', + 'Ḁ' => 'ḁ', + 'Ḃ' => 'ḃ', + 'Ḅ' => 'ḅ', + 'Ḇ' => 'ḇ', + 'Ḉ' => 'ḉ', + 'Ḋ' => 'ḋ', + 'Ḍ' => 'ḍ', + 'Ḏ' => 'ḏ', + 'Ḑ' => 'ḑ', + 'Ḓ' => 'ḓ', + 'Ḕ' => 'ḕ', + 'Ḗ' => 'ḗ', + 'Ḙ' => 'ḙ', + 'Ḛ' => 'ḛ', + 'Ḝ' => 'ḝ', + 'Ḟ' => 'ḟ', + 'Ḡ' => 'ḡ', + 'Ḣ' => 'ḣ', + 'Ḥ' => 'ḥ', + 'Ḧ' => 'ḧ', + 'Ḩ' => 'ḩ', + 'Ḫ' => 'ḫ', + 'Ḭ' => 'ḭ', + 'Ḯ' => 'ḯ', + 'Ḱ' => 'ḱ', + 'Ḳ' => 'ḳ', + 'Ḵ' => 'ḵ', + 'Ḷ' => 'ḷ', + 'Ḹ' => 'ḹ', + 'Ḻ' => 'ḻ', + 'Ḽ' => 'ḽ', + 'Ḿ' => 'ḿ', + 'Ṁ' => 'ṁ', + 'Ṃ' => 'ṃ', + 'Ṅ' => 'ṅ', + 'Ṇ' => 'ṇ', + 'Ṉ' => 'ṉ', + 'Ṋ' => 'ṋ', + 'Ṍ' => 'ṍ', + 'Ṏ' => 'ṏ', + 'Ṑ' => 'ṑ', + 'Ṓ' => 'ṓ', + 'Ṕ' => 'ṕ', + 'Ṗ' => 'ṗ', + 'Ṙ' => 'ṙ', + 'Ṛ' => 'ṛ', + 'Ṝ' => 'ṝ', + 'Ṟ' => 'ṟ', + 'Ṡ' => 'ṡ', + 'Ṣ' => 'ṣ', + 'Ṥ' => 'ṥ', + 'Ṧ' => 'ṧ', + 'Ṩ' => 'ṩ', + 'Ṫ' => 'ṫ', + 'Ṭ' => 'ṭ', + 'Ṯ' => 'ṯ', + 'Ṱ' => 'ṱ', + 'Ṳ' => 'ṳ', + 'Ṵ' => 'ṵ', + 'Ṷ' => 'ṷ', + 'Ṹ' => 'ṹ', + 'Ṻ' => 'ṻ', + 'Ṽ' => 'ṽ', + 'Ṿ' => 'ṿ', + 'Ẁ' => 'ẁ', + 'Ẃ' => 'ẃ', + 'Ẅ' => 'ẅ', + 'Ẇ' => 'ẇ', + 'Ẉ' => 'ẉ', + 'Ẋ' => 'ẋ', + 'Ẍ' => 'ẍ', + 'Ẏ' => 'ẏ', + 'Ẑ' => 'ẑ', + 'Ẓ' => 'ẓ', + 'Ẕ' => 'ẕ', + 'ẞ' => 'ß', + 'Ạ' => 'ạ', + 'Ả' => 'ả', + 'Ấ' => 'ấ', + 'Ầ' => 'ầ', + 'Ẩ' => 'ẩ', + 'Ẫ' => 'ẫ', + 'Ậ' => 'ậ', + 'Ắ' => 'ắ', + 'Ằ' => 'ằ', + 'Ẳ' => 'ẳ', + 'Ẵ' => 'ẵ', + 'Ặ' => 'ặ', + 'Ẹ' => 'ẹ', + 'Ẻ' => 'ẻ', + 'Ẽ' => 'ẽ', + 'Ế' => 'ế', + 'Ề' => 'ề', + 'Ể' => 'ể', + 'Ễ' => 'ễ', + 'Ệ' => 'ệ', + 'Ỉ' => 'ỉ', + 'Ị' => 'ị', + 'Ọ' => 'ọ', + 'Ỏ' => 'ỏ', + 'Ố' => 'ố', + 'Ồ' => 'ồ', + 'Ổ' => 'ổ', + 'Ỗ' => 'ỗ', + 'Ộ' => 'ộ', + 'Ớ' => 'ớ', + 'Ờ' => 'ờ', + 'Ở' => 'ở', + 'Ỡ' => 'ỡ', + 'Ợ' => 'ợ', + 'Ụ' => 'ụ', + 'Ủ' => 'ủ', + 'Ứ' => 'ứ', + 'Ừ' => 'ừ', + 'Ử' => 'ử', + 'Ữ' => 'ữ', + 'Ự' => 'ự', + 'Ỳ' => 'ỳ', + 'Ỵ' => 'ỵ', + 'Ỷ' => 'ỷ', + 'Ỹ' => 'ỹ', + 'Ỻ' => 'ỻ', + 'Ỽ' => 'ỽ', + 'Ỿ' => 'ỿ', + 'Ἀ' => 'ἀ', + 'Ἁ' => 'ἁ', + 'Ἂ' => 'ἂ', + 'Ἃ' => 'ἃ', + 'Ἄ' => 'ἄ', + 'Ἅ' => 'ἅ', + 'Ἆ' => 'ἆ', + 'Ἇ' => 'ἇ', + 'Ἐ' => 'ἐ', + 'Ἑ' => 'ἑ', + 'Ἒ' => 'ἒ', + 'Ἓ' => 'ἓ', + 'Ἔ' => 'ἔ', + 'Ἕ' => 'ἕ', + 'Ἠ' => 'ἠ', + 'Ἡ' => 'ἡ', + 'Ἢ' => 'ἢ', + 'Ἣ' => 'ἣ', + 'Ἤ' => 'ἤ', + 'Ἥ' => 'ἥ', + 'Ἦ' => 'ἦ', + 'Ἧ' => 'ἧ', + 'Ἰ' => 'ἰ', + 'Ἱ' => 'ἱ', + 'Ἲ' => 'ἲ', + 'Ἳ' => 'ἳ', + 'Ἴ' => 'ἴ', + 'Ἵ' => 'ἵ', + 'Ἶ' => 'ἶ', + 'Ἷ' => 'ἷ', + 'Ὀ' => 'ὀ', + 'Ὁ' => 'ὁ', + 'Ὂ' => 'ὂ', + 'Ὃ' => 'ὃ', + 'Ὄ' => 'ὄ', + 'Ὅ' => 'ὅ', + 'Ὑ' => 'ὑ', + 'Ὓ' => 'ὓ', + 'Ὕ' => 'ὕ', + 'Ὗ' => 'ὗ', + 'Ὠ' => 'ὠ', + 'Ὡ' => 'ὡ', + 'Ὢ' => 'ὢ', + 'Ὣ' => 'ὣ', + 'Ὤ' => 'ὤ', + 'Ὥ' => 'ὥ', + 'Ὦ' => 'ὦ', + 'Ὧ' => 'ὧ', + 'ᾈ' => 'ᾀ', + 'ᾉ' => 'ᾁ', + 'ᾊ' => 'ᾂ', + 'ᾋ' => 'ᾃ', + 'ᾌ' => 'ᾄ', + 'ᾍ' => 'ᾅ', + 'ᾎ' => 'ᾆ', + 'ᾏ' => 'ᾇ', + 'ᾘ' => 'ᾐ', + 'ᾙ' => 'ᾑ', + 'ᾚ' => 'ᾒ', + 'ᾛ' => 'ᾓ', + 'ᾜ' => 'ᾔ', + 'ᾝ' => 'ᾕ', + 'ᾞ' => 'ᾖ', + 'ᾟ' => 'ᾗ', + 'ᾨ' => 'ᾠ', + 'ᾩ' => 'ᾡ', + 'ᾪ' => 'ᾢ', + 'ᾫ' => 'ᾣ', + 'ᾬ' => 'ᾤ', + 'ᾭ' => 'ᾥ', + 'ᾮ' => 'ᾦ', + 'ᾯ' => 'ᾧ', + 'Ᾰ' => 'ᾰ', + 'Ᾱ' => 'ᾱ', + 'Ὰ' => 'ὰ', + 'Ά' => 'ά', + 'ᾼ' => 'ᾳ', + 'Ὲ' => 'ὲ', + 'Έ' => 'έ', + 'Ὴ' => 'ὴ', + 'Ή' => 'ή', + 'ῌ' => 'ῃ', + 'Ῐ' => 'ῐ', + 'Ῑ' => 'ῑ', + 'Ὶ' => 'ὶ', + 'Ί' => 'ί', + 'Ῠ' => 'ῠ', + 'Ῡ' => 'ῡ', + 'Ὺ' => 'ὺ', + 'Ύ' => 'ύ', + 'Ῥ' => 'ῥ', + 'Ὸ' => 'ὸ', + 'Ό' => 'ό', + 'Ὼ' => 'ὼ', + 'Ώ' => 'ώ', + 'ῼ' => 'ῳ', + 'Ω' => 'ω', + 'K' => 'k', + 'Å' => 'å', + 'Ⅎ' => 'ⅎ', + 'Ⅰ' => 'ⅰ', + 'Ⅱ' => 'ⅱ', + 'Ⅲ' => 'ⅲ', + 'Ⅳ' => 'ⅳ', + 'Ⅴ' => 'ⅴ', + 'Ⅵ' => 'ⅵ', + 'Ⅶ' => 'ⅶ', + 'Ⅷ' => 'ⅷ', + 'Ⅸ' => 'ⅸ', + 'Ⅹ' => 'ⅹ', + 'Ⅺ' => 'ⅺ', + 'Ⅻ' => 'ⅻ', + 'Ⅼ' => 'ⅼ', + 'Ⅽ' => 'ⅽ', + 'Ⅾ' => 'ⅾ', + 'Ⅿ' => 'ⅿ', + 'Ↄ' => 'ↄ', + 'Ⓐ' => 'ⓐ', + 'Ⓑ' => 'ⓑ', + 'Ⓒ' => 'ⓒ', + 'Ⓓ' => 'ⓓ', + 'Ⓔ' => 'ⓔ', + 'Ⓕ' => 'ⓕ', + 'Ⓖ' => 'ⓖ', + 'Ⓗ' => 'ⓗ', + 'Ⓘ' => 'ⓘ', + 'Ⓙ' => 'ⓙ', + 'Ⓚ' => 'ⓚ', + 'Ⓛ' => 'ⓛ', + 'Ⓜ' => 'ⓜ', + 'Ⓝ' => 'ⓝ', + 'Ⓞ' => 'ⓞ', + 'Ⓟ' => 'ⓟ', + 'Ⓠ' => 'ⓠ', + 'Ⓡ' => 'ⓡ', + 'Ⓢ' => 'ⓢ', + 'Ⓣ' => 'ⓣ', + 'Ⓤ' => 'ⓤ', + 'Ⓥ' => 'ⓥ', + 'Ⓦ' => 'ⓦ', + 'Ⓧ' => 'ⓧ', + 'Ⓨ' => 'ⓨ', + 'Ⓩ' => 'ⓩ', + 'Ⰰ' => 'ⰰ', + 'Ⰱ' => 'ⰱ', + 'Ⰲ' => 'ⰲ', + 'Ⰳ' => 'ⰳ', + 'Ⰴ' => 'ⰴ', + 'Ⰵ' => 'ⰵ', + 'Ⰶ' => 'ⰶ', + 'Ⰷ' => 'ⰷ', + 'Ⰸ' => 'ⰸ', + 'Ⰹ' => 'ⰹ', + 'Ⰺ' => 'ⰺ', + 'Ⰻ' => 'ⰻ', + 'Ⰼ' => 'ⰼ', + 'Ⰽ' => 'ⰽ', + 'Ⰾ' => 'ⰾ', + 'Ⰿ' => 'ⰿ', + 'Ⱀ' => 'ⱀ', + 'Ⱁ' => 'ⱁ', + 'Ⱂ' => 'ⱂ', + 'Ⱃ' => 'ⱃ', + 'Ⱄ' => 'ⱄ', + 'Ⱅ' => 'ⱅ', + 'Ⱆ' => 'ⱆ', + 'Ⱇ' => 'ⱇ', + 'Ⱈ' => 'ⱈ', + 'Ⱉ' => 'ⱉ', + 'Ⱊ' => 'ⱊ', + 'Ⱋ' => 'ⱋ', + 'Ⱌ' => 'ⱌ', + 'Ⱍ' => 'ⱍ', + 'Ⱎ' => 'ⱎ', + 'Ⱏ' => 'ⱏ', + 'Ⱐ' => 'ⱐ', + 'Ⱑ' => 'ⱑ', + 'Ⱒ' => 'ⱒ', + 'Ⱓ' => 'ⱓ', + 'Ⱔ' => 'ⱔ', + 'Ⱕ' => 'ⱕ', + 'Ⱖ' => 'ⱖ', + 'Ⱗ' => 'ⱗ', + 'Ⱘ' => 'ⱘ', + 'Ⱙ' => 'ⱙ', + 'Ⱚ' => 'ⱚ', + 'Ⱛ' => 'ⱛ', + 'Ⱜ' => 'ⱜ', + 'Ⱝ' => 'ⱝ', + 'Ⱞ' => 'ⱞ', + 'Ⱡ' => 'ⱡ', + 'Ɫ' => 'ɫ', + 'Ᵽ' => 'ᵽ', + 'Ɽ' => 'ɽ', + 'Ⱨ' => 'ⱨ', + 'Ⱪ' => 'ⱪ', + 'Ⱬ' => 'ⱬ', + 'Ɑ' => 'ɑ', + 'Ɱ' => 'ɱ', + 'Ɐ' => 'ɐ', + 'Ɒ' => 'ɒ', + 'Ⱳ' => 'ⱳ', + 'Ⱶ' => 'ⱶ', + 'Ȿ' => 'ȿ', + 'Ɀ' => 'ɀ', + 'Ⲁ' => 'ⲁ', + 'Ⲃ' => 'ⲃ', + 'Ⲅ' => 'ⲅ', + 'Ⲇ' => 'ⲇ', + 'Ⲉ' => 'ⲉ', + 'Ⲋ' => 'ⲋ', + 'Ⲍ' => 'ⲍ', + 'Ⲏ' => 'ⲏ', + 'Ⲑ' => 'ⲑ', + 'Ⲓ' => 'ⲓ', + 'Ⲕ' => 'ⲕ', + 'Ⲗ' => 'ⲗ', + 'Ⲙ' => 'ⲙ', + 'Ⲛ' => 'ⲛ', + 'Ⲝ' => 'ⲝ', + 'Ⲟ' => 'ⲟ', + 'Ⲡ' => 'ⲡ', + 'Ⲣ' => 'ⲣ', + 'Ⲥ' => 'ⲥ', + 'Ⲧ' => 'ⲧ', + 'Ⲩ' => 'ⲩ', + 'Ⲫ' => 'ⲫ', + 'Ⲭ' => 'ⲭ', + 'Ⲯ' => 'ⲯ', + 'Ⲱ' => 'ⲱ', + 'Ⲳ' => 'ⲳ', + 'Ⲵ' => 'ⲵ', + 'Ⲷ' => 'ⲷ', + 'Ⲹ' => 'ⲹ', + 'Ⲻ' => 'ⲻ', + 'Ⲽ' => 'ⲽ', + 'Ⲿ' => 'ⲿ', + 'Ⳁ' => 'ⳁ', + 'Ⳃ' => 'ⳃ', + 'Ⳅ' => 'ⳅ', + 'Ⳇ' => 'ⳇ', + 'Ⳉ' => 'ⳉ', + 'Ⳋ' => 'ⳋ', + 'Ⳍ' => 'ⳍ', + 'Ⳏ' => 'ⳏ', + 'Ⳑ' => 'ⳑ', + 'Ⳓ' => 'ⳓ', + 'Ⳕ' => 'ⳕ', + 'Ⳗ' => 'ⳗ', + 'Ⳙ' => 'ⳙ', + 'Ⳛ' => 'ⳛ', + 'Ⳝ' => 'ⳝ', + 'Ⳟ' => 'ⳟ', + 'Ⳡ' => 'ⳡ', + 'Ⳣ' => 'ⳣ', + 'Ⳬ' => 'ⳬ', + 'Ⳮ' => 'ⳮ', + 'Ⳳ' => 'ⳳ', + 'Ꙁ' => 'ꙁ', + 'Ꙃ' => 'ꙃ', + 'Ꙅ' => 'ꙅ', + 'Ꙇ' => 'ꙇ', + 'Ꙉ' => 'ꙉ', + 'Ꙋ' => 'ꙋ', + 'Ꙍ' => 'ꙍ', + 'Ꙏ' => 'ꙏ', + 'Ꙑ' => 'ꙑ', + 'Ꙓ' => 'ꙓ', + 'Ꙕ' => 'ꙕ', + 'Ꙗ' => 'ꙗ', + 'Ꙙ' => 'ꙙ', + 'Ꙛ' => 'ꙛ', + 'Ꙝ' => 'ꙝ', + 'Ꙟ' => 'ꙟ', + 'Ꙡ' => 'ꙡ', + 'Ꙣ' => 'ꙣ', + 'Ꙥ' => 'ꙥ', + 'Ꙧ' => 'ꙧ', + 'Ꙩ' => 'ꙩ', + 'Ꙫ' => 'ꙫ', + 'Ꙭ' => 'ꙭ', + 'Ꚁ' => 'ꚁ', + 'Ꚃ' => 'ꚃ', + 'Ꚅ' => 'ꚅ', + 'Ꚇ' => 'ꚇ', + 'Ꚉ' => 'ꚉ', + 'Ꚋ' => 'ꚋ', + 'Ꚍ' => 'ꚍ', + 'Ꚏ' => 'ꚏ', + 'Ꚑ' => 'ꚑ', + 'Ꚓ' => 'ꚓ', + 'Ꚕ' => 'ꚕ', + 'Ꚗ' => 'ꚗ', + 'Ꚙ' => 'ꚙ', + 'Ꚛ' => 'ꚛ', + 'Ꜣ' => 'ꜣ', + 'Ꜥ' => 'ꜥ', + 'Ꜧ' => 'ꜧ', + 'Ꜩ' => 'ꜩ', + 'Ꜫ' => 'ꜫ', + 'Ꜭ' => 'ꜭ', + 'Ꜯ' => 'ꜯ', + 'Ꜳ' => 'ꜳ', + 'Ꜵ' => 'ꜵ', + 'Ꜷ' => 'ꜷ', + 'Ꜹ' => 'ꜹ', + 'Ꜻ' => 'ꜻ', + 'Ꜽ' => 'ꜽ', + 'Ꜿ' => 'ꜿ', + 'Ꝁ' => 'ꝁ', + 'Ꝃ' => 'ꝃ', + 'Ꝅ' => 'ꝅ', + 'Ꝇ' => 'ꝇ', + 'Ꝉ' => 'ꝉ', + 'Ꝋ' => 'ꝋ', + 'Ꝍ' => 'ꝍ', + 'Ꝏ' => 'ꝏ', + 'Ꝑ' => 'ꝑ', + 'Ꝓ' => 'ꝓ', + 'Ꝕ' => 'ꝕ', + 'Ꝗ' => 'ꝗ', + 'Ꝙ' => 'ꝙ', + 'Ꝛ' => 'ꝛ', + 'Ꝝ' => 'ꝝ', + 'Ꝟ' => 'ꝟ', + 'Ꝡ' => 'ꝡ', + 'Ꝣ' => 'ꝣ', + 'Ꝥ' => 'ꝥ', + 'Ꝧ' => 'ꝧ', + 'Ꝩ' => 'ꝩ', + 'Ꝫ' => 'ꝫ', + 'Ꝭ' => 'ꝭ', + 'Ꝯ' => 'ꝯ', + 'Ꝺ' => 'ꝺ', + 'Ꝼ' => 'ꝼ', + 'Ᵹ' => 'ᵹ', + 'Ꝿ' => 'ꝿ', + 'Ꞁ' => 'ꞁ', + 'Ꞃ' => 'ꞃ', + 'Ꞅ' => 'ꞅ', + 'Ꞇ' => 'ꞇ', + 'Ꞌ' => 'ꞌ', + 'Ɥ' => 'ɥ', + 'Ꞑ' => 'ꞑ', + 'Ꞓ' => 'ꞓ', + 'Ꞗ' => 'ꞗ', + 'Ꞙ' => 'ꞙ', + 'Ꞛ' => 'ꞛ', + 'Ꞝ' => 'ꞝ', + 'Ꞟ' => 'ꞟ', + 'Ꞡ' => 'ꞡ', + 'Ꞣ' => 'ꞣ', + 'Ꞥ' => 'ꞥ', + 'Ꞧ' => 'ꞧ', + 'Ꞩ' => 'ꞩ', + 'Ɦ' => 'ɦ', + 'Ɜ' => 'ɜ', + 'Ɡ' => 'ɡ', + 'Ɬ' => 'ɬ', + 'Ɪ' => 'ɪ', + 'Ʞ' => 'ʞ', + 'Ʇ' => 'ʇ', + 'Ʝ' => 'ʝ', + 'Ꭓ' => 'ꭓ', + 'Ꞵ' => 'ꞵ', + 'Ꞷ' => 'ꞷ', + 'Ꞹ' => 'ꞹ', + 'Ꞻ' => 'ꞻ', + 'Ꞽ' => 'ꞽ', + 'Ꞿ' => 'ꞿ', + 'Ꟃ' => 'ꟃ', + 'Ꞔ' => 'ꞔ', + 'Ʂ' => 'ʂ', + 'Ᶎ' => 'ᶎ', + 'Ꟈ' => 'ꟈ', + 'Ꟊ' => 'ꟊ', + 'Ꟶ' => 'ꟶ', + 'A' => 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + '𐐀' => '𐐨', + '𐐁' => '𐐩', + '𐐂' => '𐐪', + '𐐃' => '𐐫', + '𐐄' => '𐐬', + '𐐅' => '𐐭', + '𐐆' => '𐐮', + '𐐇' => '𐐯', + '𐐈' => '𐐰', + '𐐉' => '𐐱', + '𐐊' => '𐐲', + '𐐋' => '𐐳', + '𐐌' => '𐐴', + '𐐍' => '𐐵', + '𐐎' => '𐐶', + '𐐏' => '𐐷', + '𐐐' => '𐐸', + '𐐑' => '𐐹', + '𐐒' => '𐐺', + '𐐓' => '𐐻', + '𐐔' => '𐐼', + '𐐕' => '𐐽', + '𐐖' => '𐐾', + '𐐗' => '𐐿', + '𐐘' => '𐑀', + '𐐙' => '𐑁', + '𐐚' => '𐑂', + '𐐛' => '𐑃', + '𐐜' => '𐑄', + '𐐝' => '𐑅', + '𐐞' => '𐑆', + '𐐟' => '𐑇', + '𐐠' => '𐑈', + '𐐡' => '𐑉', + '𐐢' => '𐑊', + '𐐣' => '𐑋', + '𐐤' => '𐑌', + '𐐥' => '𐑍', + '𐐦' => '𐑎', + '𐐧' => '𐑏', + '𐒰' => '𐓘', + '𐒱' => '𐓙', + '𐒲' => '𐓚', + '𐒳' => '𐓛', + '𐒴' => '𐓜', + '𐒵' => '𐓝', + '𐒶' => '𐓞', + '𐒷' => '𐓟', + '𐒸' => '𐓠', + '𐒹' => '𐓡', + '𐒺' => '𐓢', + '𐒻' => '𐓣', + '𐒼' => '𐓤', + '𐒽' => '𐓥', + '𐒾' => '𐓦', + '𐒿' => '𐓧', + '𐓀' => '𐓨', + '𐓁' => '𐓩', + '𐓂' => '𐓪', + '𐓃' => '𐓫', + '𐓄' => '𐓬', + '𐓅' => '𐓭', + '𐓆' => '𐓮', + '𐓇' => '𐓯', + '𐓈' => '𐓰', + '𐓉' => '𐓱', + '𐓊' => '𐓲', + '𐓋' => '𐓳', + '𐓌' => '𐓴', + '𐓍' => '𐓵', + '𐓎' => '𐓶', + '𐓏' => '𐓷', + '𐓐' => '𐓸', + '𐓑' => '𐓹', + '𐓒' => '𐓺', + '𐓓' => '𐓻', + '𐲀' => '𐳀', + '𐲁' => '𐳁', + '𐲂' => '𐳂', + '𐲃' => '𐳃', + '𐲄' => '𐳄', + '𐲅' => '𐳅', + '𐲆' => '𐳆', + '𐲇' => '𐳇', + '𐲈' => '𐳈', + '𐲉' => '𐳉', + '𐲊' => '𐳊', + '𐲋' => '𐳋', + '𐲌' => '𐳌', + '𐲍' => '𐳍', + '𐲎' => '𐳎', + '𐲏' => '𐳏', + '𐲐' => '𐳐', + '𐲑' => '𐳑', + '𐲒' => '𐳒', + '𐲓' => '𐳓', + '𐲔' => '𐳔', + '𐲕' => '𐳕', + '𐲖' => '𐳖', + '𐲗' => '𐳗', + '𐲘' => '𐳘', + '𐲙' => '𐳙', + '𐲚' => '𐳚', + '𐲛' => '𐳛', + '𐲜' => '𐳜', + '𐲝' => '𐳝', + '𐲞' => '𐳞', + '𐲟' => '𐳟', + '𐲠' => '𐳠', + '𐲡' => '𐳡', + '𐲢' => '𐳢', + '𐲣' => '𐳣', + '𐲤' => '𐳤', + '𐲥' => '𐳥', + '𐲦' => '𐳦', + '𐲧' => '𐳧', + '𐲨' => '𐳨', + '𐲩' => '𐳩', + '𐲪' => '𐳪', + '𐲫' => '𐳫', + '𐲬' => '𐳬', + '𐲭' => '𐳭', + '𐲮' => '𐳮', + '𐲯' => '𐳯', + '𐲰' => '𐳰', + '𐲱' => '𐳱', + '𐲲' => '𐳲', + '𑢠' => '𑣀', + '𑢡' => '𑣁', + '𑢢' => '𑣂', + '𑢣' => '𑣃', + '𑢤' => '𑣄', + '𑢥' => '𑣅', + '𑢦' => '𑣆', + '𑢧' => '𑣇', + '𑢨' => '𑣈', + '𑢩' => '𑣉', + '𑢪' => '𑣊', + '𑢫' => '𑣋', + '𑢬' => '𑣌', + '𑢭' => '𑣍', + '𑢮' => '𑣎', + '𑢯' => '𑣏', + '𑢰' => '𑣐', + '𑢱' => '𑣑', + '𑢲' => '𑣒', + '𑢳' => '𑣓', + '𑢴' => '𑣔', + '𑢵' => '𑣕', + '𑢶' => '𑣖', + '𑢷' => '𑣗', + '𑢸' => '𑣘', + '𑢹' => '𑣙', + '𑢺' => '𑣚', + '𑢻' => '𑣛', + '𑢼' => '𑣜', + '𑢽' => '𑣝', + '𑢾' => '𑣞', + '𑢿' => '𑣟', + '𖹀' => '𖹠', + '𖹁' => '𖹡', + '𖹂' => '𖹢', + '𖹃' => '𖹣', + '𖹄' => '𖹤', + '𖹅' => '𖹥', + '𖹆' => '𖹦', + '𖹇' => '𖹧', + '𖹈' => '𖹨', + '𖹉' => '𖹩', + '𖹊' => '𖹪', + '𖹋' => '𖹫', + '𖹌' => '𖹬', + '𖹍' => '𖹭', + '𖹎' => '𖹮', + '𖹏' => '𖹯', + '𖹐' => '𖹰', + '𖹑' => '𖹱', + '𖹒' => '𖹲', + '𖹓' => '𖹳', + '𖹔' => '𖹴', + '𖹕' => '𖹵', + '𖹖' => '𖹶', + '𖹗' => '𖹷', + '𖹘' => '𖹸', + '𖹙' => '𖹹', + '𖹚' => '𖹺', + '𖹛' => '𖹻', + '𖹜' => '𖹼', + '𖹝' => '𖹽', + '𖹞' => '𖹾', + '𖹟' => '𖹿', + '𞤀' => '𞤢', + '𞤁' => '𞤣', + '𞤂' => '𞤤', + '𞤃' => '𞤥', + '𞤄' => '𞤦', + '𞤅' => '𞤧', + '𞤆' => '𞤨', + '𞤇' => '𞤩', + '𞤈' => '𞤪', + '𞤉' => '𞤫', + '𞤊' => '𞤬', + '𞤋' => '𞤭', + '𞤌' => '𞤮', + '𞤍' => '𞤯', + '𞤎' => '𞤰', + '𞤏' => '𞤱', + '𞤐' => '𞤲', + '𞤑' => '𞤳', + '𞤒' => '𞤴', + '𞤓' => '𞤵', + '𞤔' => '𞤶', + '𞤕' => '𞤷', + '𞤖' => '𞤸', + '𞤗' => '𞤹', + '𞤘' => '𞤺', + '𞤙' => '𞤻', + '𞤚' => '𞤼', + '𞤛' => '𞤽', + '𞤜' => '𞤾', + '𞤝' => '𞤿', + '𞤞' => '𞥀', + '𞤟' => '𞥁', + '𞤠' => '𞥂', + '𞤡' => '𞥃', +); diff --git a/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 0000000..2a8f6e7 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ + 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + 'µ' => 'Μ', + 'à' => 'À', + 'á' => 'Á', + 'â' => 'Â', + 'ã' => 'Ã', + 'ä' => 'Ä', + 'å' => 'Å', + 'æ' => 'Æ', + 'ç' => 'Ç', + 'è' => 'È', + 'é' => 'É', + 'ê' => 'Ê', + 'ë' => 'Ë', + 'ì' => 'Ì', + 'í' => 'Í', + 'î' => 'Î', + 'ï' => 'Ï', + 'ð' => 'Ð', + 'ñ' => 'Ñ', + 'ò' => 'Ò', + 'ó' => 'Ó', + 'ô' => 'Ô', + 'õ' => 'Õ', + 'ö' => 'Ö', + 'ø' => 'Ø', + 'ù' => 'Ù', + 'ú' => 'Ú', + 'û' => 'Û', + 'ü' => 'Ü', + 'ý' => 'Ý', + 'þ' => 'Þ', + 'ÿ' => 'Ÿ', + 'ā' => 'Ā', + 'ă' => 'Ă', + 'ą' => 'Ą', + 'ć' => 'Ć', + 'ĉ' => 'Ĉ', + 'ċ' => 'Ċ', + 'č' => 'Č', + 'ď' => 'Ď', + 'đ' => 'Đ', + 'ē' => 'Ē', + 'ĕ' => 'Ĕ', + 'ė' => 'Ė', + 'ę' => 'Ę', + 'ě' => 'Ě', + 'ĝ' => 'Ĝ', + 'ğ' => 'Ğ', + 'ġ' => 'Ġ', + 'ģ' => 'Ģ', + 'ĥ' => 'Ĥ', + 'ħ' => 'Ħ', + 'ĩ' => 'Ĩ', + 'ī' => 'Ī', + 'ĭ' => 'Ĭ', + 'į' => 'Į', + 'ı' => 'I', + 'ij' => 'IJ', + 'ĵ' => 'Ĵ', + 'ķ' => 'Ķ', + 'ĺ' => 'Ĺ', + 'ļ' => 'Ļ', + 'ľ' => 'Ľ', + 'ŀ' => 'Ŀ', + 'ł' => 'Ł', + 'ń' => 'Ń', + 'ņ' => 'Ņ', + 'ň' => 'Ň', + 'ŋ' => 'Ŋ', + 'ō' => 'Ō', + 'ŏ' => 'Ŏ', + 'ő' => 'Ő', + 'œ' => 'Œ', + 'ŕ' => 'Ŕ', + 'ŗ' => 'Ŗ', + 'ř' => 'Ř', + 'ś' => 'Ś', + 'ŝ' => 'Ŝ', + 'ş' => 'Ş', + 'š' => 'Š', + 'ţ' => 'Ţ', + 'ť' => 'Ť', + 'ŧ' => 'Ŧ', + 'ũ' => 'Ũ', + 'ū' => 'Ū', + 'ŭ' => 'Ŭ', + 'ů' => 'Ů', + 'ű' => 'Ű', + 'ų' => 'Ų', + 'ŵ' => 'Ŵ', + 'ŷ' => 'Ŷ', + 'ź' => 'Ź', + 'ż' => 'Ż', + 'ž' => 'Ž', + 'ſ' => 'S', + 'ƀ' => 'Ƀ', + 'ƃ' => 'Ƃ', + 'ƅ' => 'Ƅ', + 'ƈ' => 'Ƈ', + 'ƌ' => 'Ƌ', + 'ƒ' => 'Ƒ', + 'ƕ' => 'Ƕ', + 'ƙ' => 'Ƙ', + 'ƚ' => 'Ƚ', + 'ƞ' => 'Ƞ', + 'ơ' => 'Ơ', + 'ƣ' => 'Ƣ', + 'ƥ' => 'Ƥ', + 'ƨ' => 'Ƨ', + 'ƭ' => 'Ƭ', + 'ư' => 'Ư', + 'ƴ' => 'Ƴ', + 'ƶ' => 'Ƶ', + 'ƹ' => 'Ƹ', + 'ƽ' => 'Ƽ', + 'ƿ' => 'Ƿ', + 'Dž' => 'DŽ', + 'dž' => 'DŽ', + 'Lj' => 'LJ', + 'lj' => 'LJ', + 'Nj' => 'NJ', + 'nj' => 'NJ', + 'ǎ' => 'Ǎ', + 'ǐ' => 'Ǐ', + 'ǒ' => 'Ǒ', + 'ǔ' => 'Ǔ', + 'ǖ' => 'Ǖ', + 'ǘ' => 'Ǘ', + 'ǚ' => 'Ǚ', + 'ǜ' => 'Ǜ', + 'ǝ' => 'Ǝ', + 'ǟ' => 'Ǟ', + 'ǡ' => 'Ǡ', + 'ǣ' => 'Ǣ', + 'ǥ' => 'Ǥ', + 'ǧ' => 'Ǧ', + 'ǩ' => 'Ǩ', + 'ǫ' => 'Ǫ', + 'ǭ' => 'Ǭ', + 'ǯ' => 'Ǯ', + 'Dz' => 'DZ', + 'dz' => 'DZ', + 'ǵ' => 'Ǵ', + 'ǹ' => 'Ǹ', + 'ǻ' => 'Ǻ', + 'ǽ' => 'Ǽ', + 'ǿ' => 'Ǿ', + 'ȁ' => 'Ȁ', + 'ȃ' => 'Ȃ', + 'ȅ' => 'Ȅ', + 'ȇ' => 'Ȇ', + 'ȉ' => 'Ȉ', + 'ȋ' => 'Ȋ', + 'ȍ' => 'Ȍ', + 'ȏ' => 'Ȏ', + 'ȑ' => 'Ȑ', + 'ȓ' => 'Ȓ', + 'ȕ' => 'Ȕ', + 'ȗ' => 'Ȗ', + 'ș' => 'Ș', + 'ț' => 'Ț', + 'ȝ' => 'Ȝ', + 'ȟ' => 'Ȟ', + 'ȣ' => 'Ȣ', + 'ȥ' => 'Ȥ', + 'ȧ' => 'Ȧ', + 'ȩ' => 'Ȩ', + 'ȫ' => 'Ȫ', + 'ȭ' => 'Ȭ', + 'ȯ' => 'Ȯ', + 'ȱ' => 'Ȱ', + 'ȳ' => 'Ȳ', + 'ȼ' => 'Ȼ', + 'ȿ' => 'Ȿ', + 'ɀ' => 'Ɀ', + 'ɂ' => 'Ɂ', + 'ɇ' => 'Ɇ', + 'ɉ' => 'Ɉ', + 'ɋ' => 'Ɋ', + 'ɍ' => 'Ɍ', + 'ɏ' => 'Ɏ', + 'ɐ' => 'Ɐ', + 'ɑ' => 'Ɑ', + 'ɒ' => 'Ɒ', + 'ɓ' => 'Ɓ', + 'ɔ' => 'Ɔ', + 'ɖ' => 'Ɖ', + 'ɗ' => 'Ɗ', + 'ə' => 'Ə', + 'ɛ' => 'Ɛ', + 'ɜ' => 'Ɜ', + 'ɠ' => 'Ɠ', + 'ɡ' => 'Ɡ', + 'ɣ' => 'Ɣ', + 'ɥ' => 'Ɥ', + 'ɦ' => 'Ɦ', + 'ɨ' => 'Ɨ', + 'ɩ' => 'Ɩ', + 'ɪ' => 'Ɪ', + 'ɫ' => 'Ɫ', + 'ɬ' => 'Ɬ', + 'ɯ' => 'Ɯ', + 'ɱ' => 'Ɱ', + 'ɲ' => 'Ɲ', + 'ɵ' => 'Ɵ', + 'ɽ' => 'Ɽ', + 'ʀ' => 'Ʀ', + 'ʂ' => 'Ʂ', + 'ʃ' => 'Ʃ', + 'ʇ' => 'Ʇ', + 'ʈ' => 'Ʈ', + 'ʉ' => 'Ʉ', + 'ʊ' => 'Ʊ', + 'ʋ' => 'Ʋ', + 'ʌ' => 'Ʌ', + 'ʒ' => 'Ʒ', + 'ʝ' => 'Ʝ', + 'ʞ' => 'Ʞ', + 'ͅ' => 'Ι', + 'ͱ' => 'Ͱ', + 'ͳ' => 'Ͳ', + 'ͷ' => 'Ͷ', + 'ͻ' => 'Ͻ', + 'ͼ' => 'Ͼ', + 'ͽ' => 'Ͽ', + 'ά' => 'Ά', + 'έ' => 'Έ', + 'ή' => 'Ή', + 'ί' => 'Ί', + 'α' => 'Α', + 'β' => 'Β', + 'γ' => 'Γ', + 'δ' => 'Δ', + 'ε' => 'Ε', + 'ζ' => 'Ζ', + 'η' => 'Η', + 'θ' => 'Θ', + 'ι' => 'Ι', + 'κ' => 'Κ', + 'λ' => 'Λ', + 'μ' => 'Μ', + 'ν' => 'Ν', + 'ξ' => 'Ξ', + 'ο' => 'Ο', + 'π' => 'Π', + 'ρ' => 'Ρ', + 'ς' => 'Σ', + 'σ' => 'Σ', + 'τ' => 'Τ', + 'υ' => 'Υ', + 'φ' => 'Φ', + 'χ' => 'Χ', + 'ψ' => 'Ψ', + 'ω' => 'Ω', + 'ϊ' => 'Ϊ', + 'ϋ' => 'Ϋ', + 'ό' => 'Ό', + 'ύ' => 'Ύ', + 'ώ' => 'Ώ', + 'ϐ' => 'Β', + 'ϑ' => 'Θ', + 'ϕ' => 'Φ', + 'ϖ' => 'Π', + 'ϗ' => 'Ϗ', + 'ϙ' => 'Ϙ', + 'ϛ' => 'Ϛ', + 'ϝ' => 'Ϝ', + 'ϟ' => 'Ϟ', + 'ϡ' => 'Ϡ', + 'ϣ' => 'Ϣ', + 'ϥ' => 'Ϥ', + 'ϧ' => 'Ϧ', + 'ϩ' => 'Ϩ', + 'ϫ' => 'Ϫ', + 'ϭ' => 'Ϭ', + 'ϯ' => 'Ϯ', + 'ϰ' => 'Κ', + 'ϱ' => 'Ρ', + 'ϲ' => 'Ϲ', + 'ϳ' => 'Ϳ', + 'ϵ' => 'Ε', + 'ϸ' => 'Ϸ', + 'ϻ' => 'Ϻ', + 'а' => 'А', + 'б' => 'Б', + 'в' => 'В', + 'г' => 'Г', + 'д' => 'Д', + 'е' => 'Е', + 'ж' => 'Ж', + 'з' => 'З', + 'и' => 'И', + 'й' => 'Й', + 'к' => 'К', + 'л' => 'Л', + 'м' => 'М', + 'н' => 'Н', + 'о' => 'О', + 'п' => 'П', + 'р' => 'Р', + 'с' => 'С', + 'т' => 'Т', + 'у' => 'У', + 'ф' => 'Ф', + 'х' => 'Х', + 'ц' => 'Ц', + 'ч' => 'Ч', + 'ш' => 'Ш', + 'щ' => 'Щ', + 'ъ' => 'Ъ', + 'ы' => 'Ы', + 'ь' => 'Ь', + 'э' => 'Э', + 'ю' => 'Ю', + 'я' => 'Я', + 'ѐ' => 'Ѐ', + 'ё' => 'Ё', + 'ђ' => 'Ђ', + 'ѓ' => 'Ѓ', + 'є' => 'Є', + 'ѕ' => 'Ѕ', + 'і' => 'І', + 'ї' => 'Ї', + 'ј' => 'Ј', + 'љ' => 'Љ', + 'њ' => 'Њ', + 'ћ' => 'Ћ', + 'ќ' => 'Ќ', + 'ѝ' => 'Ѝ', + 'ў' => 'Ў', + 'џ' => 'Џ', + 'ѡ' => 'Ѡ', + 'ѣ' => 'Ѣ', + 'ѥ' => 'Ѥ', + 'ѧ' => 'Ѧ', + 'ѩ' => 'Ѩ', + 'ѫ' => 'Ѫ', + 'ѭ' => 'Ѭ', + 'ѯ' => 'Ѯ', + 'ѱ' => 'Ѱ', + 'ѳ' => 'Ѳ', + 'ѵ' => 'Ѵ', + 'ѷ' => 'Ѷ', + 'ѹ' => 'Ѹ', + 'ѻ' => 'Ѻ', + 'ѽ' => 'Ѽ', + 'ѿ' => 'Ѿ', + 'ҁ' => 'Ҁ', + 'ҋ' => 'Ҋ', + 'ҍ' => 'Ҍ', + 'ҏ' => 'Ҏ', + 'ґ' => 'Ґ', + 'ғ' => 'Ғ', + 'ҕ' => 'Ҕ', + 'җ' => 'Җ', + 'ҙ' => 'Ҙ', + 'қ' => 'Қ', + 'ҝ' => 'Ҝ', + 'ҟ' => 'Ҟ', + 'ҡ' => 'Ҡ', + 'ң' => 'Ң', + 'ҥ' => 'Ҥ', + 'ҧ' => 'Ҧ', + 'ҩ' => 'Ҩ', + 'ҫ' => 'Ҫ', + 'ҭ' => 'Ҭ', + 'ү' => 'Ү', + 'ұ' => 'Ұ', + 'ҳ' => 'Ҳ', + 'ҵ' => 'Ҵ', + 'ҷ' => 'Ҷ', + 'ҹ' => 'Ҹ', + 'һ' => 'Һ', + 'ҽ' => 'Ҽ', + 'ҿ' => 'Ҿ', + 'ӂ' => 'Ӂ', + 'ӄ' => 'Ӄ', + 'ӆ' => 'Ӆ', + 'ӈ' => 'Ӈ', + 'ӊ' => 'Ӊ', + 'ӌ' => 'Ӌ', + 'ӎ' => 'Ӎ', + 'ӏ' => 'Ӏ', + 'ӑ' => 'Ӑ', + 'ӓ' => 'Ӓ', + 'ӕ' => 'Ӕ', + 'ӗ' => 'Ӗ', + 'ә' => 'Ә', + 'ӛ' => 'Ӛ', + 'ӝ' => 'Ӝ', + 'ӟ' => 'Ӟ', + 'ӡ' => 'Ӡ', + 'ӣ' => 'Ӣ', + 'ӥ' => 'Ӥ', + 'ӧ' => 'Ӧ', + 'ө' => 'Ө', + 'ӫ' => 'Ӫ', + 'ӭ' => 'Ӭ', + 'ӯ' => 'Ӯ', + 'ӱ' => 'Ӱ', + 'ӳ' => 'Ӳ', + 'ӵ' => 'Ӵ', + 'ӷ' => 'Ӷ', + 'ӹ' => 'Ӹ', + 'ӻ' => 'Ӻ', + 'ӽ' => 'Ӽ', + 'ӿ' => 'Ӿ', + 'ԁ' => 'Ԁ', + 'ԃ' => 'Ԃ', + 'ԅ' => 'Ԅ', + 'ԇ' => 'Ԇ', + 'ԉ' => 'Ԉ', + 'ԋ' => 'Ԋ', + 'ԍ' => 'Ԍ', + 'ԏ' => 'Ԏ', + 'ԑ' => 'Ԑ', + 'ԓ' => 'Ԓ', + 'ԕ' => 'Ԕ', + 'ԗ' => 'Ԗ', + 'ԙ' => 'Ԙ', + 'ԛ' => 'Ԛ', + 'ԝ' => 'Ԝ', + 'ԟ' => 'Ԟ', + 'ԡ' => 'Ԡ', + 'ԣ' => 'Ԣ', + 'ԥ' => 'Ԥ', + 'ԧ' => 'Ԧ', + 'ԩ' => 'Ԩ', + 'ԫ' => 'Ԫ', + 'ԭ' => 'Ԭ', + 'ԯ' => 'Ԯ', + 'ա' => 'Ա', + 'բ' => 'Բ', + 'գ' => 'Գ', + 'դ' => 'Դ', + 'ե' => 'Ե', + 'զ' => 'Զ', + 'է' => 'Է', + 'ը' => 'Ը', + 'թ' => 'Թ', + 'ժ' => 'Ժ', + 'ի' => 'Ի', + 'լ' => 'Լ', + 'խ' => 'Խ', + 'ծ' => 'Ծ', + 'կ' => 'Կ', + 'հ' => 'Հ', + 'ձ' => 'Ձ', + 'ղ' => 'Ղ', + 'ճ' => 'Ճ', + 'մ' => 'Մ', + 'յ' => 'Յ', + 'ն' => 'Ն', + 'շ' => 'Շ', + 'ո' => 'Ո', + 'չ' => 'Չ', + 'պ' => 'Պ', + 'ջ' => 'Ջ', + 'ռ' => 'Ռ', + 'ս' => 'Ս', + 'վ' => 'Վ', + 'տ' => 'Տ', + 'ր' => 'Ր', + 'ց' => 'Ց', + 'ւ' => 'Ւ', + 'փ' => 'Փ', + 'ք' => 'Ք', + 'օ' => 'Օ', + 'ֆ' => 'Ֆ', + 'ა' => 'Ა', + 'ბ' => 'Ბ', + 'გ' => 'Გ', + 'დ' => 'Დ', + 'ე' => 'Ე', + 'ვ' => 'Ვ', + 'ზ' => 'Ზ', + 'თ' => 'Თ', + 'ი' => 'Ი', + 'კ' => 'Კ', + 'ლ' => 'Ლ', + 'მ' => 'Მ', + 'ნ' => 'Ნ', + 'ო' => 'Ო', + 'პ' => 'Პ', + 'ჟ' => 'Ჟ', + 'რ' => 'Რ', + 'ს' => 'Ს', + 'ტ' => 'Ტ', + 'უ' => 'Უ', + 'ფ' => 'Ფ', + 'ქ' => 'Ქ', + 'ღ' => 'Ღ', + 'ყ' => 'Ყ', + 'შ' => 'Შ', + 'ჩ' => 'Ჩ', + 'ც' => 'Ც', + 'ძ' => 'Ძ', + 'წ' => 'Წ', + 'ჭ' => 'Ჭ', + 'ხ' => 'Ხ', + 'ჯ' => 'Ჯ', + 'ჰ' => 'Ჰ', + 'ჱ' => 'Ჱ', + 'ჲ' => 'Ჲ', + 'ჳ' => 'Ჳ', + 'ჴ' => 'Ჴ', + 'ჵ' => 'Ჵ', + 'ჶ' => 'Ჶ', + 'ჷ' => 'Ჷ', + 'ჸ' => 'Ჸ', + 'ჹ' => 'Ჹ', + 'ჺ' => 'Ჺ', + 'ჽ' => 'Ჽ', + 'ჾ' => 'Ჾ', + 'ჿ' => 'Ჿ', + 'ᏸ' => 'Ᏸ', + 'ᏹ' => 'Ᏹ', + 'ᏺ' => 'Ᏺ', + 'ᏻ' => 'Ᏻ', + 'ᏼ' => 'Ᏼ', + 'ᏽ' => 'Ᏽ', + 'ᲀ' => 'В', + 'ᲁ' => 'Д', + 'ᲂ' => 'О', + 'ᲃ' => 'С', + 'ᲄ' => 'Т', + 'ᲅ' => 'Т', + 'ᲆ' => 'Ъ', + 'ᲇ' => 'Ѣ', + 'ᲈ' => 'Ꙋ', + 'ᵹ' => 'Ᵹ', + 'ᵽ' => 'Ᵽ', + 'ᶎ' => 'Ᶎ', + 'ḁ' => 'Ḁ', + 'ḃ' => 'Ḃ', + 'ḅ' => 'Ḅ', + 'ḇ' => 'Ḇ', + 'ḉ' => 'Ḉ', + 'ḋ' => 'Ḋ', + 'ḍ' => 'Ḍ', + 'ḏ' => 'Ḏ', + 'ḑ' => 'Ḑ', + 'ḓ' => 'Ḓ', + 'ḕ' => 'Ḕ', + 'ḗ' => 'Ḗ', + 'ḙ' => 'Ḙ', + 'ḛ' => 'Ḛ', + 'ḝ' => 'Ḝ', + 'ḟ' => 'Ḟ', + 'ḡ' => 'Ḡ', + 'ḣ' => 'Ḣ', + 'ḥ' => 'Ḥ', + 'ḧ' => 'Ḧ', + 'ḩ' => 'Ḩ', + 'ḫ' => 'Ḫ', + 'ḭ' => 'Ḭ', + 'ḯ' => 'Ḯ', + 'ḱ' => 'Ḱ', + 'ḳ' => 'Ḳ', + 'ḵ' => 'Ḵ', + 'ḷ' => 'Ḷ', + 'ḹ' => 'Ḹ', + 'ḻ' => 'Ḻ', + 'ḽ' => 'Ḽ', + 'ḿ' => 'Ḿ', + 'ṁ' => 'Ṁ', + 'ṃ' => 'Ṃ', + 'ṅ' => 'Ṅ', + 'ṇ' => 'Ṇ', + 'ṉ' => 'Ṉ', + 'ṋ' => 'Ṋ', + 'ṍ' => 'Ṍ', + 'ṏ' => 'Ṏ', + 'ṑ' => 'Ṑ', + 'ṓ' => 'Ṓ', + 'ṕ' => 'Ṕ', + 'ṗ' => 'Ṗ', + 'ṙ' => 'Ṙ', + 'ṛ' => 'Ṛ', + 'ṝ' => 'Ṝ', + 'ṟ' => 'Ṟ', + 'ṡ' => 'Ṡ', + 'ṣ' => 'Ṣ', + 'ṥ' => 'Ṥ', + 'ṧ' => 'Ṧ', + 'ṩ' => 'Ṩ', + 'ṫ' => 'Ṫ', + 'ṭ' => 'Ṭ', + 'ṯ' => 'Ṯ', + 'ṱ' => 'Ṱ', + 'ṳ' => 'Ṳ', + 'ṵ' => 'Ṵ', + 'ṷ' => 'Ṷ', + 'ṹ' => 'Ṹ', + 'ṻ' => 'Ṻ', + 'ṽ' => 'Ṽ', + 'ṿ' => 'Ṿ', + 'ẁ' => 'Ẁ', + 'ẃ' => 'Ẃ', + 'ẅ' => 'Ẅ', + 'ẇ' => 'Ẇ', + 'ẉ' => 'Ẉ', + 'ẋ' => 'Ẋ', + 'ẍ' => 'Ẍ', + 'ẏ' => 'Ẏ', + 'ẑ' => 'Ẑ', + 'ẓ' => 'Ẓ', + 'ẕ' => 'Ẕ', + 'ẛ' => 'Ṡ', + 'ạ' => 'Ạ', + 'ả' => 'Ả', + 'ấ' => 'Ấ', + 'ầ' => 'Ầ', + 'ẩ' => 'Ẩ', + 'ẫ' => 'Ẫ', + 'ậ' => 'Ậ', + 'ắ' => 'Ắ', + 'ằ' => 'Ằ', + 'ẳ' => 'Ẳ', + 'ẵ' => 'Ẵ', + 'ặ' => 'Ặ', + 'ẹ' => 'Ẹ', + 'ẻ' => 'Ẻ', + 'ẽ' => 'Ẽ', + 'ế' => 'Ế', + 'ề' => 'Ề', + 'ể' => 'Ể', + 'ễ' => 'Ễ', + 'ệ' => 'Ệ', + 'ỉ' => 'Ỉ', + 'ị' => 'Ị', + 'ọ' => 'Ọ', + 'ỏ' => 'Ỏ', + 'ố' => 'Ố', + 'ồ' => 'Ồ', + 'ổ' => 'Ổ', + 'ỗ' => 'Ỗ', + 'ộ' => 'Ộ', + 'ớ' => 'Ớ', + 'ờ' => 'Ờ', + 'ở' => 'Ở', + 'ỡ' => 'Ỡ', + 'ợ' => 'Ợ', + 'ụ' => 'Ụ', + 'ủ' => 'Ủ', + 'ứ' => 'Ứ', + 'ừ' => 'Ừ', + 'ử' => 'Ử', + 'ữ' => 'Ữ', + 'ự' => 'Ự', + 'ỳ' => 'Ỳ', + 'ỵ' => 'Ỵ', + 'ỷ' => 'Ỷ', + 'ỹ' => 'Ỹ', + 'ỻ' => 'Ỻ', + 'ỽ' => 'Ỽ', + 'ỿ' => 'Ỿ', + 'ἀ' => 'Ἀ', + 'ἁ' => 'Ἁ', + 'ἂ' => 'Ἂ', + 'ἃ' => 'Ἃ', + 'ἄ' => 'Ἄ', + 'ἅ' => 'Ἅ', + 'ἆ' => 'Ἆ', + 'ἇ' => 'Ἇ', + 'ἐ' => 'Ἐ', + 'ἑ' => 'Ἑ', + 'ἒ' => 'Ἒ', + 'ἓ' => 'Ἓ', + 'ἔ' => 'Ἔ', + 'ἕ' => 'Ἕ', + 'ἠ' => 'Ἠ', + 'ἡ' => 'Ἡ', + 'ἢ' => 'Ἢ', + 'ἣ' => 'Ἣ', + 'ἤ' => 'Ἤ', + 'ἥ' => 'Ἥ', + 'ἦ' => 'Ἦ', + 'ἧ' => 'Ἧ', + 'ἰ' => 'Ἰ', + 'ἱ' => 'Ἱ', + 'ἲ' => 'Ἲ', + 'ἳ' => 'Ἳ', + 'ἴ' => 'Ἴ', + 'ἵ' => 'Ἵ', + 'ἶ' => 'Ἶ', + 'ἷ' => 'Ἷ', + 'ὀ' => 'Ὀ', + 'ὁ' => 'Ὁ', + 'ὂ' => 'Ὂ', + 'ὃ' => 'Ὃ', + 'ὄ' => 'Ὄ', + 'ὅ' => 'Ὅ', + 'ὑ' => 'Ὑ', + 'ὓ' => 'Ὓ', + 'ὕ' => 'Ὕ', + 'ὗ' => 'Ὗ', + 'ὠ' => 'Ὠ', + 'ὡ' => 'Ὡ', + 'ὢ' => 'Ὢ', + 'ὣ' => 'Ὣ', + 'ὤ' => 'Ὤ', + 'ὥ' => 'Ὥ', + 'ὦ' => 'Ὦ', + 'ὧ' => 'Ὧ', + 'ὰ' => 'Ὰ', + 'ά' => 'Ά', + 'ὲ' => 'Ὲ', + 'έ' => 'Έ', + 'ὴ' => 'Ὴ', + 'ή' => 'Ή', + 'ὶ' => 'Ὶ', + 'ί' => 'Ί', + 'ὸ' => 'Ὸ', + 'ό' => 'Ό', + 'ὺ' => 'Ὺ', + 'ύ' => 'Ύ', + 'ὼ' => 'Ὼ', + 'ώ' => 'Ώ', + 'ᾀ' => 'ἈΙ', + 'ᾁ' => 'ἉΙ', + 'ᾂ' => 'ἊΙ', + 'ᾃ' => 'ἋΙ', + 'ᾄ' => 'ἌΙ', + 'ᾅ' => 'ἍΙ', + 'ᾆ' => 'ἎΙ', + 'ᾇ' => 'ἏΙ', + 'ᾐ' => 'ἨΙ', + 'ᾑ' => 'ἩΙ', + 'ᾒ' => 'ἪΙ', + 'ᾓ' => 'ἫΙ', + 'ᾔ' => 'ἬΙ', + 'ᾕ' => 'ἭΙ', + 'ᾖ' => 'ἮΙ', + 'ᾗ' => 'ἯΙ', + 'ᾠ' => 'ὨΙ', + 'ᾡ' => 'ὩΙ', + 'ᾢ' => 'ὪΙ', + 'ᾣ' => 'ὫΙ', + 'ᾤ' => 'ὬΙ', + 'ᾥ' => 'ὭΙ', + 'ᾦ' => 'ὮΙ', + 'ᾧ' => 'ὯΙ', + 'ᾰ' => 'Ᾰ', + 'ᾱ' => 'Ᾱ', + 'ᾳ' => 'ΑΙ', + 'ι' => 'Ι', + 'ῃ' => 'ΗΙ', + 'ῐ' => 'Ῐ', + 'ῑ' => 'Ῑ', + 'ῠ' => 'Ῠ', + 'ῡ' => 'Ῡ', + 'ῥ' => 'Ῥ', + 'ῳ' => 'ΩΙ', + 'ⅎ' => 'Ⅎ', + 'ⅰ' => 'Ⅰ', + 'ⅱ' => 'Ⅱ', + 'ⅲ' => 'Ⅲ', + 'ⅳ' => 'Ⅳ', + 'ⅴ' => 'Ⅴ', + 'ⅵ' => 'Ⅵ', + 'ⅶ' => 'Ⅶ', + 'ⅷ' => 'Ⅷ', + 'ⅸ' => 'Ⅸ', + 'ⅹ' => 'Ⅹ', + 'ⅺ' => 'Ⅺ', + 'ⅻ' => 'Ⅻ', + 'ⅼ' => 'Ⅼ', + 'ⅽ' => 'Ⅽ', + 'ⅾ' => 'Ⅾ', + 'ⅿ' => 'Ⅿ', + 'ↄ' => 'Ↄ', + 'ⓐ' => 'Ⓐ', + 'ⓑ' => 'Ⓑ', + 'ⓒ' => 'Ⓒ', + 'ⓓ' => 'Ⓓ', + 'ⓔ' => 'Ⓔ', + 'ⓕ' => 'Ⓕ', + 'ⓖ' => 'Ⓖ', + 'ⓗ' => 'Ⓗ', + 'ⓘ' => 'Ⓘ', + 'ⓙ' => 'Ⓙ', + 'ⓚ' => 'Ⓚ', + 'ⓛ' => 'Ⓛ', + 'ⓜ' => 'Ⓜ', + 'ⓝ' => 'Ⓝ', + 'ⓞ' => 'Ⓞ', + 'ⓟ' => 'Ⓟ', + 'ⓠ' => 'Ⓠ', + 'ⓡ' => 'Ⓡ', + 'ⓢ' => 'Ⓢ', + 'ⓣ' => 'Ⓣ', + 'ⓤ' => 'Ⓤ', + 'ⓥ' => 'Ⓥ', + 'ⓦ' => 'Ⓦ', + 'ⓧ' => 'Ⓧ', + 'ⓨ' => 'Ⓨ', + 'ⓩ' => 'Ⓩ', + 'ⰰ' => 'Ⰰ', + 'ⰱ' => 'Ⰱ', + 'ⰲ' => 'Ⰲ', + 'ⰳ' => 'Ⰳ', + 'ⰴ' => 'Ⰴ', + 'ⰵ' => 'Ⰵ', + 'ⰶ' => 'Ⰶ', + 'ⰷ' => 'Ⰷ', + 'ⰸ' => 'Ⰸ', + 'ⰹ' => 'Ⰹ', + 'ⰺ' => 'Ⰺ', + 'ⰻ' => 'Ⰻ', + 'ⰼ' => 'Ⰼ', + 'ⰽ' => 'Ⰽ', + 'ⰾ' => 'Ⰾ', + 'ⰿ' => 'Ⰿ', + 'ⱀ' => 'Ⱀ', + 'ⱁ' => 'Ⱁ', + 'ⱂ' => 'Ⱂ', + 'ⱃ' => 'Ⱃ', + 'ⱄ' => 'Ⱄ', + 'ⱅ' => 'Ⱅ', + 'ⱆ' => 'Ⱆ', + 'ⱇ' => 'Ⱇ', + 'ⱈ' => 'Ⱈ', + 'ⱉ' => 'Ⱉ', + 'ⱊ' => 'Ⱊ', + 'ⱋ' => 'Ⱋ', + 'ⱌ' => 'Ⱌ', + 'ⱍ' => 'Ⱍ', + 'ⱎ' => 'Ⱎ', + 'ⱏ' => 'Ⱏ', + 'ⱐ' => 'Ⱐ', + 'ⱑ' => 'Ⱑ', + 'ⱒ' => 'Ⱒ', + 'ⱓ' => 'Ⱓ', + 'ⱔ' => 'Ⱔ', + 'ⱕ' => 'Ⱕ', + 'ⱖ' => 'Ⱖ', + 'ⱗ' => 'Ⱗ', + 'ⱘ' => 'Ⱘ', + 'ⱙ' => 'Ⱙ', + 'ⱚ' => 'Ⱚ', + 'ⱛ' => 'Ⱛ', + 'ⱜ' => 'Ⱜ', + 'ⱝ' => 'Ⱝ', + 'ⱞ' => 'Ⱞ', + 'ⱡ' => 'Ⱡ', + 'ⱥ' => 'Ⱥ', + 'ⱦ' => 'Ⱦ', + 'ⱨ' => 'Ⱨ', + 'ⱪ' => 'Ⱪ', + 'ⱬ' => 'Ⱬ', + 'ⱳ' => 'Ⱳ', + 'ⱶ' => 'Ⱶ', + 'ⲁ' => 'Ⲁ', + 'ⲃ' => 'Ⲃ', + 'ⲅ' => 'Ⲅ', + 'ⲇ' => 'Ⲇ', + 'ⲉ' => 'Ⲉ', + 'ⲋ' => 'Ⲋ', + 'ⲍ' => 'Ⲍ', + 'ⲏ' => 'Ⲏ', + 'ⲑ' => 'Ⲑ', + 'ⲓ' => 'Ⲓ', + 'ⲕ' => 'Ⲕ', + 'ⲗ' => 'Ⲗ', + 'ⲙ' => 'Ⲙ', + 'ⲛ' => 'Ⲛ', + 'ⲝ' => 'Ⲝ', + 'ⲟ' => 'Ⲟ', + 'ⲡ' => 'Ⲡ', + 'ⲣ' => 'Ⲣ', + 'ⲥ' => 'Ⲥ', + 'ⲧ' => 'Ⲧ', + 'ⲩ' => 'Ⲩ', + 'ⲫ' => 'Ⲫ', + 'ⲭ' => 'Ⲭ', + 'ⲯ' => 'Ⲯ', + 'ⲱ' => 'Ⲱ', + 'ⲳ' => 'Ⲳ', + 'ⲵ' => 'Ⲵ', + 'ⲷ' => 'Ⲷ', + 'ⲹ' => 'Ⲹ', + 'ⲻ' => 'Ⲻ', + 'ⲽ' => 'Ⲽ', + 'ⲿ' => 'Ⲿ', + 'ⳁ' => 'Ⳁ', + 'ⳃ' => 'Ⳃ', + 'ⳅ' => 'Ⳅ', + 'ⳇ' => 'Ⳇ', + 'ⳉ' => 'Ⳉ', + 'ⳋ' => 'Ⳋ', + 'ⳍ' => 'Ⳍ', + 'ⳏ' => 'Ⳏ', + 'ⳑ' => 'Ⳑ', + 'ⳓ' => 'Ⳓ', + 'ⳕ' => 'Ⳕ', + 'ⳗ' => 'Ⳗ', + 'ⳙ' => 'Ⳙ', + 'ⳛ' => 'Ⳛ', + 'ⳝ' => 'Ⳝ', + 'ⳟ' => 'Ⳟ', + 'ⳡ' => 'Ⳡ', + 'ⳣ' => 'Ⳣ', + 'ⳬ' => 'Ⳬ', + 'ⳮ' => 'Ⳮ', + 'ⳳ' => 'Ⳳ', + 'ⴀ' => 'Ⴀ', + 'ⴁ' => 'Ⴁ', + 'ⴂ' => 'Ⴂ', + 'ⴃ' => 'Ⴃ', + 'ⴄ' => 'Ⴄ', + 'ⴅ' => 'Ⴅ', + 'ⴆ' => 'Ⴆ', + 'ⴇ' => 'Ⴇ', + 'ⴈ' => 'Ⴈ', + 'ⴉ' => 'Ⴉ', + 'ⴊ' => 'Ⴊ', + 'ⴋ' => 'Ⴋ', + 'ⴌ' => 'Ⴌ', + 'ⴍ' => 'Ⴍ', + 'ⴎ' => 'Ⴎ', + 'ⴏ' => 'Ⴏ', + 'ⴐ' => 'Ⴐ', + 'ⴑ' => 'Ⴑ', + 'ⴒ' => 'Ⴒ', + 'ⴓ' => 'Ⴓ', + 'ⴔ' => 'Ⴔ', + 'ⴕ' => 'Ⴕ', + 'ⴖ' => 'Ⴖ', + 'ⴗ' => 'Ⴗ', + 'ⴘ' => 'Ⴘ', + 'ⴙ' => 'Ⴙ', + 'ⴚ' => 'Ⴚ', + 'ⴛ' => 'Ⴛ', + 'ⴜ' => 'Ⴜ', + 'ⴝ' => 'Ⴝ', + 'ⴞ' => 'Ⴞ', + 'ⴟ' => 'Ⴟ', + 'ⴠ' => 'Ⴠ', + 'ⴡ' => 'Ⴡ', + 'ⴢ' => 'Ⴢ', + 'ⴣ' => 'Ⴣ', + 'ⴤ' => 'Ⴤ', + 'ⴥ' => 'Ⴥ', + 'ⴧ' => 'Ⴧ', + 'ⴭ' => 'Ⴭ', + 'ꙁ' => 'Ꙁ', + 'ꙃ' => 'Ꙃ', + 'ꙅ' => 'Ꙅ', + 'ꙇ' => 'Ꙇ', + 'ꙉ' => 'Ꙉ', + 'ꙋ' => 'Ꙋ', + 'ꙍ' => 'Ꙍ', + 'ꙏ' => 'Ꙏ', + 'ꙑ' => 'Ꙑ', + 'ꙓ' => 'Ꙓ', + 'ꙕ' => 'Ꙕ', + 'ꙗ' => 'Ꙗ', + 'ꙙ' => 'Ꙙ', + 'ꙛ' => 'Ꙛ', + 'ꙝ' => 'Ꙝ', + 'ꙟ' => 'Ꙟ', + 'ꙡ' => 'Ꙡ', + 'ꙣ' => 'Ꙣ', + 'ꙥ' => 'Ꙥ', + 'ꙧ' => 'Ꙧ', + 'ꙩ' => 'Ꙩ', + 'ꙫ' => 'Ꙫ', + 'ꙭ' => 'Ꙭ', + 'ꚁ' => 'Ꚁ', + 'ꚃ' => 'Ꚃ', + 'ꚅ' => 'Ꚅ', + 'ꚇ' => 'Ꚇ', + 'ꚉ' => 'Ꚉ', + 'ꚋ' => 'Ꚋ', + 'ꚍ' => 'Ꚍ', + 'ꚏ' => 'Ꚏ', + 'ꚑ' => 'Ꚑ', + 'ꚓ' => 'Ꚓ', + 'ꚕ' => 'Ꚕ', + 'ꚗ' => 'Ꚗ', + 'ꚙ' => 'Ꚙ', + 'ꚛ' => 'Ꚛ', + 'ꜣ' => 'Ꜣ', + 'ꜥ' => 'Ꜥ', + 'ꜧ' => 'Ꜧ', + 'ꜩ' => 'Ꜩ', + 'ꜫ' => 'Ꜫ', + 'ꜭ' => 'Ꜭ', + 'ꜯ' => 'Ꜯ', + 'ꜳ' => 'Ꜳ', + 'ꜵ' => 'Ꜵ', + 'ꜷ' => 'Ꜷ', + 'ꜹ' => 'Ꜹ', + 'ꜻ' => 'Ꜻ', + 'ꜽ' => 'Ꜽ', + 'ꜿ' => 'Ꜿ', + 'ꝁ' => 'Ꝁ', + 'ꝃ' => 'Ꝃ', + 'ꝅ' => 'Ꝅ', + 'ꝇ' => 'Ꝇ', + 'ꝉ' => 'Ꝉ', + 'ꝋ' => 'Ꝋ', + 'ꝍ' => 'Ꝍ', + 'ꝏ' => 'Ꝏ', + 'ꝑ' => 'Ꝑ', + 'ꝓ' => 'Ꝓ', + 'ꝕ' => 'Ꝕ', + 'ꝗ' => 'Ꝗ', + 'ꝙ' => 'Ꝙ', + 'ꝛ' => 'Ꝛ', + 'ꝝ' => 'Ꝝ', + 'ꝟ' => 'Ꝟ', + 'ꝡ' => 'Ꝡ', + 'ꝣ' => 'Ꝣ', + 'ꝥ' => 'Ꝥ', + 'ꝧ' => 'Ꝧ', + 'ꝩ' => 'Ꝩ', + 'ꝫ' => 'Ꝫ', + 'ꝭ' => 'Ꝭ', + 'ꝯ' => 'Ꝯ', + 'ꝺ' => 'Ꝺ', + 'ꝼ' => 'Ꝼ', + 'ꝿ' => 'Ꝿ', + 'ꞁ' => 'Ꞁ', + 'ꞃ' => 'Ꞃ', + 'ꞅ' => 'Ꞅ', + 'ꞇ' => 'Ꞇ', + 'ꞌ' => 'Ꞌ', + 'ꞑ' => 'Ꞑ', + 'ꞓ' => 'Ꞓ', + 'ꞔ' => 'Ꞔ', + 'ꞗ' => 'Ꞗ', + 'ꞙ' => 'Ꞙ', + 'ꞛ' => 'Ꞛ', + 'ꞝ' => 'Ꞝ', + 'ꞟ' => 'Ꞟ', + 'ꞡ' => 'Ꞡ', + 'ꞣ' => 'Ꞣ', + 'ꞥ' => 'Ꞥ', + 'ꞧ' => 'Ꞧ', + 'ꞩ' => 'Ꞩ', + 'ꞵ' => 'Ꞵ', + 'ꞷ' => 'Ꞷ', + 'ꞹ' => 'Ꞹ', + 'ꞻ' => 'Ꞻ', + 'ꞽ' => 'Ꞽ', + 'ꞿ' => 'Ꞿ', + 'ꟃ' => 'Ꟃ', + 'ꟈ' => 'Ꟈ', + 'ꟊ' => 'Ꟊ', + 'ꟶ' => 'Ꟶ', + 'ꭓ' => 'Ꭓ', + 'ꭰ' => 'Ꭰ', + 'ꭱ' => 'Ꭱ', + 'ꭲ' => 'Ꭲ', + 'ꭳ' => 'Ꭳ', + 'ꭴ' => 'Ꭴ', + 'ꭵ' => 'Ꭵ', + 'ꭶ' => 'Ꭶ', + 'ꭷ' => 'Ꭷ', + 'ꭸ' => 'Ꭸ', + 'ꭹ' => 'Ꭹ', + 'ꭺ' => 'Ꭺ', + 'ꭻ' => 'Ꭻ', + 'ꭼ' => 'Ꭼ', + 'ꭽ' => 'Ꭽ', + 'ꭾ' => 'Ꭾ', + 'ꭿ' => 'Ꭿ', + 'ꮀ' => 'Ꮀ', + 'ꮁ' => 'Ꮁ', + 'ꮂ' => 'Ꮂ', + 'ꮃ' => 'Ꮃ', + 'ꮄ' => 'Ꮄ', + 'ꮅ' => 'Ꮅ', + 'ꮆ' => 'Ꮆ', + 'ꮇ' => 'Ꮇ', + 'ꮈ' => 'Ꮈ', + 'ꮉ' => 'Ꮉ', + 'ꮊ' => 'Ꮊ', + 'ꮋ' => 'Ꮋ', + 'ꮌ' => 'Ꮌ', + 'ꮍ' => 'Ꮍ', + 'ꮎ' => 'Ꮎ', + 'ꮏ' => 'Ꮏ', + 'ꮐ' => 'Ꮐ', + 'ꮑ' => 'Ꮑ', + 'ꮒ' => 'Ꮒ', + 'ꮓ' => 'Ꮓ', + 'ꮔ' => 'Ꮔ', + 'ꮕ' => 'Ꮕ', + 'ꮖ' => 'Ꮖ', + 'ꮗ' => 'Ꮗ', + 'ꮘ' => 'Ꮘ', + 'ꮙ' => 'Ꮙ', + 'ꮚ' => 'Ꮚ', + 'ꮛ' => 'Ꮛ', + 'ꮜ' => 'Ꮜ', + 'ꮝ' => 'Ꮝ', + 'ꮞ' => 'Ꮞ', + 'ꮟ' => 'Ꮟ', + 'ꮠ' => 'Ꮠ', + 'ꮡ' => 'Ꮡ', + 'ꮢ' => 'Ꮢ', + 'ꮣ' => 'Ꮣ', + 'ꮤ' => 'Ꮤ', + 'ꮥ' => 'Ꮥ', + 'ꮦ' => 'Ꮦ', + 'ꮧ' => 'Ꮧ', + 'ꮨ' => 'Ꮨ', + 'ꮩ' => 'Ꮩ', + 'ꮪ' => 'Ꮪ', + 'ꮫ' => 'Ꮫ', + 'ꮬ' => 'Ꮬ', + 'ꮭ' => 'Ꮭ', + 'ꮮ' => 'Ꮮ', + 'ꮯ' => 'Ꮯ', + 'ꮰ' => 'Ꮰ', + 'ꮱ' => 'Ꮱ', + 'ꮲ' => 'Ꮲ', + 'ꮳ' => 'Ꮳ', + 'ꮴ' => 'Ꮴ', + 'ꮵ' => 'Ꮵ', + 'ꮶ' => 'Ꮶ', + 'ꮷ' => 'Ꮷ', + 'ꮸ' => 'Ꮸ', + 'ꮹ' => 'Ꮹ', + 'ꮺ' => 'Ꮺ', + 'ꮻ' => 'Ꮻ', + 'ꮼ' => 'Ꮼ', + 'ꮽ' => 'Ꮽ', + 'ꮾ' => 'Ꮾ', + 'ꮿ' => 'Ꮿ', + 'a' => 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + '𐐨' => '𐐀', + '𐐩' => '𐐁', + '𐐪' => '𐐂', + '𐐫' => '𐐃', + '𐐬' => '𐐄', + '𐐭' => '𐐅', + '𐐮' => '𐐆', + '𐐯' => '𐐇', + '𐐰' => '𐐈', + '𐐱' => '𐐉', + '𐐲' => '𐐊', + '𐐳' => '𐐋', + '𐐴' => '𐐌', + '𐐵' => '𐐍', + '𐐶' => '𐐎', + '𐐷' => '𐐏', + '𐐸' => '𐐐', + '𐐹' => '𐐑', + '𐐺' => '𐐒', + '𐐻' => '𐐓', + '𐐼' => '𐐔', + '𐐽' => '𐐕', + '𐐾' => '𐐖', + '𐐿' => '𐐗', + '𐑀' => '𐐘', + '𐑁' => '𐐙', + '𐑂' => '𐐚', + '𐑃' => '𐐛', + '𐑄' => '𐐜', + '𐑅' => '𐐝', + '𐑆' => '𐐞', + '𐑇' => '𐐟', + '𐑈' => '𐐠', + '𐑉' => '𐐡', + '𐑊' => '𐐢', + '𐑋' => '𐐣', + '𐑌' => '𐐤', + '𐑍' => '𐐥', + '𐑎' => '𐐦', + '𐑏' => '𐐧', + '𐓘' => '𐒰', + '𐓙' => '𐒱', + '𐓚' => '𐒲', + '𐓛' => '𐒳', + '𐓜' => '𐒴', + '𐓝' => '𐒵', + '𐓞' => '𐒶', + '𐓟' => '𐒷', + '𐓠' => '𐒸', + '𐓡' => '𐒹', + '𐓢' => '𐒺', + '𐓣' => '𐒻', + '𐓤' => '𐒼', + '𐓥' => '𐒽', + '𐓦' => '𐒾', + '𐓧' => '𐒿', + '𐓨' => '𐓀', + '𐓩' => '𐓁', + '𐓪' => '𐓂', + '𐓫' => '𐓃', + '𐓬' => '𐓄', + '𐓭' => '𐓅', + '𐓮' => '𐓆', + '𐓯' => '𐓇', + '𐓰' => '𐓈', + '𐓱' => '𐓉', + '𐓲' => '𐓊', + '𐓳' => '𐓋', + '𐓴' => '𐓌', + '𐓵' => '𐓍', + '𐓶' => '𐓎', + '𐓷' => '𐓏', + '𐓸' => '𐓐', + '𐓹' => '𐓑', + '𐓺' => '𐓒', + '𐓻' => '𐓓', + '𐳀' => '𐲀', + '𐳁' => '𐲁', + '𐳂' => '𐲂', + '𐳃' => '𐲃', + '𐳄' => '𐲄', + '𐳅' => '𐲅', + '𐳆' => '𐲆', + '𐳇' => '𐲇', + '𐳈' => '𐲈', + '𐳉' => '𐲉', + '𐳊' => '𐲊', + '𐳋' => '𐲋', + '𐳌' => '𐲌', + '𐳍' => '𐲍', + '𐳎' => '𐲎', + '𐳏' => '𐲏', + '𐳐' => '𐲐', + '𐳑' => '𐲑', + '𐳒' => '𐲒', + '𐳓' => '𐲓', + '𐳔' => '𐲔', + '𐳕' => '𐲕', + '𐳖' => '𐲖', + '𐳗' => '𐲗', + '𐳘' => '𐲘', + '𐳙' => '𐲙', + '𐳚' => '𐲚', + '𐳛' => '𐲛', + '𐳜' => '𐲜', + '𐳝' => '𐲝', + '𐳞' => '𐲞', + '𐳟' => '𐲟', + '𐳠' => '𐲠', + '𐳡' => '𐲡', + '𐳢' => '𐲢', + '𐳣' => '𐲣', + '𐳤' => '𐲤', + '𐳥' => '𐲥', + '𐳦' => '𐲦', + '𐳧' => '𐲧', + '𐳨' => '𐲨', + '𐳩' => '𐲩', + '𐳪' => '𐲪', + '𐳫' => '𐲫', + '𐳬' => '𐲬', + '𐳭' => '𐲭', + '𐳮' => '𐲮', + '𐳯' => '𐲯', + '𐳰' => '𐲰', + '𐳱' => '𐲱', + '𐳲' => '𐲲', + '𑣀' => '𑢠', + '𑣁' => '𑢡', + '𑣂' => '𑢢', + '𑣃' => '𑢣', + '𑣄' => '𑢤', + '𑣅' => '𑢥', + '𑣆' => '𑢦', + '𑣇' => '𑢧', + '𑣈' => '𑢨', + '𑣉' => '𑢩', + '𑣊' => '𑢪', + '𑣋' => '𑢫', + '𑣌' => '𑢬', + '𑣍' => '𑢭', + '𑣎' => '𑢮', + '𑣏' => '𑢯', + '𑣐' => '𑢰', + '𑣑' => '𑢱', + '𑣒' => '𑢲', + '𑣓' => '𑢳', + '𑣔' => '𑢴', + '𑣕' => '𑢵', + '𑣖' => '𑢶', + '𑣗' => '𑢷', + '𑣘' => '𑢸', + '𑣙' => '𑢹', + '𑣚' => '𑢺', + '𑣛' => '𑢻', + '𑣜' => '𑢼', + '𑣝' => '𑢽', + '𑣞' => '𑢾', + '𑣟' => '𑢿', + '𖹠' => '𖹀', + '𖹡' => '𖹁', + '𖹢' => '𖹂', + '𖹣' => '𖹃', + '𖹤' => '𖹄', + '𖹥' => '𖹅', + '𖹦' => '𖹆', + '𖹧' => '𖹇', + '𖹨' => '𖹈', + '𖹩' => '𖹉', + '𖹪' => '𖹊', + '𖹫' => '𖹋', + '𖹬' => '𖹌', + '𖹭' => '𖹍', + '𖹮' => '𖹎', + '𖹯' => '𖹏', + '𖹰' => '𖹐', + '𖹱' => '𖹑', + '𖹲' => '𖹒', + '𖹳' => '𖹓', + '𖹴' => '𖹔', + '𖹵' => '𖹕', + '𖹶' => '𖹖', + '𖹷' => '𖹗', + '𖹸' => '𖹘', + '𖹹' => '𖹙', + '𖹺' => '𖹚', + '𖹻' => '𖹛', + '𖹼' => '𖹜', + '𖹽' => '𖹝', + '𖹾' => '𖹞', + '𖹿' => '𖹟', + '𞤢' => '𞤀', + '𞤣' => '𞤁', + '𞤤' => '𞤂', + '𞤥' => '𞤃', + '𞤦' => '𞤄', + '𞤧' => '𞤅', + '𞤨' => '𞤆', + '𞤩' => '𞤇', + '𞤪' => '𞤈', + '𞤫' => '𞤉', + '𞤬' => '𞤊', + '𞤭' => '𞤋', + '𞤮' => '𞤌', + '𞤯' => '𞤍', + '𞤰' => '𞤎', + '𞤱' => '𞤏', + '𞤲' => '𞤐', + '𞤳' => '𞤑', + '𞤴' => '𞤒', + '𞤵' => '𞤓', + '𞤶' => '𞤔', + '𞤷' => '𞤕', + '𞤸' => '𞤖', + '𞤹' => '𞤗', + '𞤺' => '𞤘', + '𞤻' => '𞤙', + '𞤼' => '𞤚', + '𞤽' => '𞤛', + '𞤾' => '𞤜', + '𞤿' => '𞤝', + '𞥀' => '𞤞', + '𞥁' => '𞤟', + '𞥂' => '𞤠', + '𞥃' => '𞤡', + 'ß' => 'SS', + 'ff' => 'FF', + 'fi' => 'FI', + 'fl' => 'FL', + 'ffi' => 'FFI', + 'ffl' => 'FFL', + 'ſt' => 'ST', + 'st' => 'ST', + 'և' => 'ԵՒ', + 'ﬓ' => 'ՄՆ', + 'ﬔ' => 'ՄԵ', + 'ﬕ' => 'ՄԻ', + 'ﬖ' => 'ՎՆ', + 'ﬗ' => 'ՄԽ', + 'ʼn' => 'ʼN', + 'ΐ' => 'Ϊ́', + 'ΰ' => 'Ϋ́', + 'ǰ' => 'J̌', + 'ẖ' => 'H̱', + 'ẗ' => 'T̈', + 'ẘ' => 'W̊', + 'ẙ' => 'Y̊', + 'ẚ' => 'Aʾ', + 'ὐ' => 'Υ̓', + 'ὒ' => 'Υ̓̀', + 'ὔ' => 'Υ̓́', + 'ὖ' => 'Υ̓͂', + 'ᾶ' => 'Α͂', + 'ῆ' => 'Η͂', + 'ῒ' => 'Ϊ̀', + 'ΐ' => 'Ϊ́', + 'ῖ' => 'Ι͂', + 'ῗ' => 'Ϊ͂', + 'ῢ' => 'Ϋ̀', + 'ΰ' => 'Ϋ́', + 'ῤ' => 'Ρ̓', + 'ῦ' => 'Υ͂', + 'ῧ' => 'Ϋ͂', + 'ῶ' => 'Ω͂', + 'ᾈ' => 'ἈΙ', + 'ᾉ' => 'ἉΙ', + 'ᾊ' => 'ἊΙ', + 'ᾋ' => 'ἋΙ', + 'ᾌ' => 'ἌΙ', + 'ᾍ' => 'ἍΙ', + 'ᾎ' => 'ἎΙ', + 'ᾏ' => 'ἏΙ', + 'ᾘ' => 'ἨΙ', + 'ᾙ' => 'ἩΙ', + 'ᾚ' => 'ἪΙ', + 'ᾛ' => 'ἫΙ', + 'ᾜ' => 'ἬΙ', + 'ᾝ' => 'ἭΙ', + 'ᾞ' => 'ἮΙ', + 'ᾟ' => 'ἯΙ', + 'ᾨ' => 'ὨΙ', + 'ᾩ' => 'ὩΙ', + 'ᾪ' => 'ὪΙ', + 'ᾫ' => 'ὫΙ', + 'ᾬ' => 'ὬΙ', + 'ᾭ' => 'ὭΙ', + 'ᾮ' => 'ὮΙ', + 'ᾯ' => 'ὯΙ', + 'ᾼ' => 'ΑΙ', + 'ῌ' => 'ΗΙ', + 'ῼ' => 'ΩΙ', + 'ᾲ' => 'ᾺΙ', + 'ᾴ' => 'ΆΙ', + 'ῂ' => 'ῊΙ', + 'ῄ' => 'ΉΙ', + 'ῲ' => 'ῺΙ', + 'ῴ' => 'ΏΙ', + 'ᾷ' => 'Α͂Ι', + 'ῇ' => 'Η͂Ι', + 'ῷ' => 'Ω͂Ι', +); diff --git a/cacme/vendor/symfony/polyfill-mbstring/bootstrap.php b/cacme/vendor/symfony/polyfill-mbstring/bootstrap.php new file mode 100644 index 0000000..ecf1a03 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); } +} +if (!function_exists('mb_language')) { + function mb_language($language = null) { return p\Mbstring::mb_language($language); } +} +if (!function_exists('mb_list_encodings')) { + function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { + function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; } +} +if (!function_exists('mb_strlen')) { + function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); } +} +if (!function_exists('mb_substr')) { + function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strstr')) { + function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_get_info')) { + function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } +} +if (!function_exists('mb_http_output')) { + function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); } +} + +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); } +} + +if (!function_exists('mb_ord')) { + function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } +} +if (!function_exists('mb_str_split')) { + function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } +} + +if (!function_exists('mb_str_pad')) { + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } +} + +if (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); +} diff --git a/cacme/vendor/symfony/polyfill-mbstring/bootstrap80.php b/cacme/vendor/symfony/polyfill-mbstring/bootstrap80.php new file mode 100644 index 0000000..2f9fb5b --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/bootstrap80.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } +} +if (!function_exists('mb_language')) { + function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } +} +if (!function_exists('mb_list_encodings')) { + function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { + function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } +} +if (!function_exists('mb_strlen')) { + function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } +} +if (!function_exists('mb_substr')) { + function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strstr')) { + function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_get_info')) { + function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); } +} +if (!function_exists('mb_http_output')) { + function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } +} + +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } +} + +if (!function_exists('mb_ord')) { + function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } +} +if (!function_exists('mb_str_split')) { + function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } +} + +if (!function_exists('mb_str_pad')) { + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } +} + +if (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); +} diff --git a/cacme/vendor/symfony/polyfill-mbstring/composer.json b/cacme/vendor/symfony/polyfill-mbstring/composer.json new file mode 100644 index 0000000..943e502 --- /dev/null +++ b/cacme/vendor/symfony/polyfill-mbstring/composer.json @@ -0,0 +1,41 @@ +{ + "name": "symfony/polyfill-mbstring", + "type": "library", + "description": "Symfony polyfill for the Mbstring extension", + "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/cacme/vendor/symfony/service-contracts/.gitignore b/cacme/vendor/symfony/service-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/cacme/vendor/symfony/service-contracts/Attribute/Required.php b/cacme/vendor/symfony/service-contracts/Attribute/Required.php new file mode 100644 index 0000000..9df8511 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/Attribute/Required.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\Contracts\Service\Attribute; + +/** + * A required dependency. + * + * This attribute indicates that a property holds a required dependency. The annotated property or method should be + * considered during the instantiation process of the containing class. + * + * @author Alexander M. Turek + */ +#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] +final class Required +{ +} diff --git a/cacme/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/cacme/vendor/symfony/service-contracts/Attribute/SubscribedService.php new file mode 100644 index 0000000..10d1bc3 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/Attribute/SubscribedService.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 Symfony\Contracts\Service\Attribute; + +use Symfony\Contracts\Service\ServiceSubscriberTrait; + +/** + * Use with {@see ServiceSubscriberTrait} to mark a method's return type + * as a subscribed service. + * + * @author Kevin Bond + */ +#[\Attribute(\Attribute::TARGET_METHOD)] +final class SubscribedService +{ + /** + * @param string|null $key The key to use for the service + * If null, use "ClassName::methodName" + */ + public function __construct( + public ?string $key = null + ) { + } +} diff --git a/cacme/vendor/symfony/service-contracts/CHANGELOG.md b/cacme/vendor/symfony/service-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/cacme/vendor/symfony/service-contracts/LICENSE b/cacme/vendor/symfony/service-contracts/LICENSE new file mode 100644 index 0000000..74cdc2d --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2022 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/cacme/vendor/symfony/service-contracts/README.md b/cacme/vendor/symfony/service-contracts/README.md new file mode 100644 index 0000000..41e054a --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/README.md @@ -0,0 +1,9 @@ +Symfony Service Contracts +========================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful - and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/cacme/vendor/symfony/service-contracts/ResetInterface.php b/cacme/vendor/symfony/service-contracts/ResetInterface.php new file mode 100644 index 0000000..1af1075 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/ResetInterface.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\Contracts\Service; + +/** + * Provides a way to reset an object to its initial state. + * + * When calling the "reset()" method on an object, it should be put back to its + * initial state. This usually means clearing any internal buffers and forwarding + * the call to internal dependencies. All properties of the object should be put + * back to the same state it had when it was first ready to use. + * + * This method could be called, for example, to recycle objects that are used as + * services, so that they can be used to handle several requests in the same + * process loop (note that we advise making your services stateless instead of + * implementing this interface when possible.) + */ +interface ResetInterface +{ + public function reset(); +} diff --git a/cacme/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/cacme/vendor/symfony/service-contracts/ServiceLocatorTrait.php new file mode 100644 index 0000000..19d3e80 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/ServiceLocatorTrait.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 Symfony\Contracts\Service; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(ContainerExceptionInterface::class); +class_exists(NotFoundExceptionInterface::class); + +/** + * A trait to help implement ServiceProviderInterface. + * + * @author Robin Chalas + * @author Nicolas Grekas + */ +trait ServiceLocatorTrait +{ + private array $factories; + private array $loading = []; + private array $providedTypes; + + /** + * @param callable[] $factories + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + */ + public function has(string $id): bool + { + return isset($this->factories[$id]); + } + + /** + * {@inheritdoc} + */ + public function get(string $id): mixed + { + if (!isset($this->factories[$id])) { + throw $this->createNotFoundException($id); + } + + if (isset($this->loading[$id])) { + $ids = array_values($this->loading); + $ids = \array_slice($this->loading, array_search($id, $ids)); + $ids[] = $id; + + throw $this->createCircularReferenceException($id, $ids); + } + + $this->loading[$id] = $id; + try { + return $this->factories[$id]($this); + } finally { + unset($this->loading[$id]); + } + } + + /** + * {@inheritdoc} + */ + public function getProvidedServices(): array + { + if (!isset($this->providedTypes)) { + $this->providedTypes = []; + + foreach ($this->factories as $name => $factory) { + if (!\is_callable($factory)) { + $this->providedTypes[$name] = '?'; + } else { + $type = (new \ReflectionFunction($factory))->getReturnType(); + + $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; + } + } + } + + return $this->providedTypes; + } + + private function createNotFoundException(string $id): NotFoundExceptionInterface + { + if (!$alternatives = array_keys($this->factories)) { + $message = 'is empty...'; + } else { + $last = array_pop($alternatives); + if ($alternatives) { + $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); + } else { + $message = sprintf('only knows about the "%s" service.', $last); + } + } + + if ($this->loading) { + $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); + } else { + $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); + } + + return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { + }; + } + + private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface + { + return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { + }; + } +} diff --git a/cacme/vendor/symfony/service-contracts/ServiceProviderInterface.php b/cacme/vendor/symfony/service-contracts/ServiceProviderInterface.php new file mode 100644 index 0000000..c60ad0b --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/ServiceProviderInterface.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\Contracts\Service; + +use Psr\Container\ContainerInterface; + +/** + * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. + * + * @author Nicolas Grekas + * @author Mateusz Sip + */ +interface ServiceProviderInterface extends ContainerInterface +{ + /** + * Returns an associative array of service types keyed by the identifiers provided by the current container. + * + * Examples: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface + * * ['foo' => '?'] means the container provides service name "foo" of unspecified type + * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null + * + * @return string[] The provided service types, keyed by service names + */ + public function getProvidedServices(): array; +} diff --git a/cacme/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/cacme/vendor/symfony/service-contracts/ServiceSubscriberInterface.php new file mode 100644 index 0000000..881ab97 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/ServiceSubscriberInterface.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\Contracts\Service; + +/** + * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. + * + * The getSubscribedServices method returns an array of service types required by such instances, + * optionally keyed by the service names used internally. Service types that start with an interrogation + * mark "?" are optional, while the other ones are mandatory service dependencies. + * + * The injected service locators SHOULD NOT allow access to any other services not specified by the method. + * + * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. + * This interface does not dictate any injection method for these service locators, although constructor + * injection is recommended. + * + * @author Nicolas Grekas + */ +interface ServiceSubscriberInterface +{ + /** + * Returns an array of service types required by such instances, optionally keyed by the service names used internally. + * + * For mandatory dependencies: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name + * internally to fetch a service which must implement Psr\Log\LoggerInterface. + * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name + * internally to fetch an iterable of Psr\Log\LoggerInterface instances. + * * ['Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] + * + * otherwise: + * + * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency + * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency + * * ['?Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] + * + * @return string[] The required service types, optionally keyed by service names + */ + public static function getSubscribedServices(): array; +} diff --git a/cacme/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/cacme/vendor/symfony/service-contracts/ServiceSubscriberTrait.php new file mode 100644 index 0000000..ee9d9d9 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/ServiceSubscriberTrait.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\Contracts\Service; + +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\Attribute\SubscribedService; + +/** + * Implementation of ServiceSubscriberInterface that determines subscribed services from + * method return types. Service ids are available as "ClassName::methodName". + * + * @author Kevin Bond + */ +trait ServiceSubscriberTrait +{ + /** @var ContainerInterface */ + protected $container; + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices(): array + { + $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; + + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if (self::class !== $method->getDeclaringClass()->name) { + continue; + } + + if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { + continue; + } + + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); + } + + if (!$returnType = $method->getReturnType()) { + throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + } + + $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; + + if ($returnType->allowsNull()) { + $serviceId = '?'.$serviceId; + } + + $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; + } + + return $services; + } + + /** + * @required + */ + public function setContainer(ContainerInterface $container): ?ContainerInterface + { + $this->container = $container; + + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + return parent::setContainer($container); + } + + return null; + } +} diff --git a/cacme/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/cacme/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php new file mode 100644 index 0000000..88f6a06 --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/Test/ServiceLocatorTest.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 Symfony\Contracts\Service\Test; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; + +abstract class ServiceLocatorTest extends TestCase +{ + protected function getServiceLocator(array $factories): ContainerInterface + { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + if (!$this->getExpectedException()) { + $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException(\Psr\Container\ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } +} diff --git a/cacme/vendor/symfony/service-contracts/composer.json b/cacme/vendor/symfony/service-contracts/composer.json new file mode 100644 index 0000000..d3b047f --- /dev/null +++ b/cacme/vendor/symfony/service-contracts/composer.json @@ -0,0 +1,41 @@ +{ + "name": "symfony/service-contracts", + "type": "library", + "description": "Generic abstractions related to writing services", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.0.2", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Service\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/cacme/vendor/symfony/string/AbstractString.php b/cacme/vendor/symfony/string/AbstractString.php new file mode 100644 index 0000000..cf96a83 --- /dev/null +++ b/cacme/vendor/symfony/string/AbstractString.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 Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; +use Symfony\Component\String\Exception\RuntimeException; + +/** + * Represents a string of abstract characters. + * + * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). + * This class is the abstract type to use as a type-hint when the logic you want to + * implement doesn't care about the exact variant it deals with. + * + * @author Nicolas Grekas + * @author Hugo Hamon + * + * @throws ExceptionInterface + */ +abstract class AbstractString implements \Stringable, \JsonSerializable +{ + public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER; + public const PREG_SET_ORDER = \PREG_SET_ORDER; + public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE; + public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL; + + public const PREG_SPLIT = 0; + public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY; + public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE; + public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE; + + protected $string = ''; + protected $ignoreCase = false; + + abstract public function __construct(string $string = ''); + + /** + * Unwraps instances of AbstractString back to strings. + * + * @return string[]|array + */ + public static function unwrap(array $values): array + { + foreach ($values as $k => $v) { + if ($v instanceof self) { + $values[$k] = $v->__toString(); + } elseif (\is_array($v) && $values[$k] !== $v = static::unwrap($v)) { + $values[$k] = $v; + } + } + + return $values; + } + + /** + * Wraps (and normalizes) strings in instances of AbstractString. + * + * @return static[]|array + */ + public static function wrap(array $values): array + { + $i = 0; + $keys = null; + + foreach ($values as $k => $v) { + if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) { + $keys = $keys ?? array_keys($values); + $keys[$i] = $j; + } + + if (\is_string($v)) { + $values[$k] = new static($v); + } elseif (\is_array($v) && $values[$k] !== $v = static::wrap($v)) { + $values[$k] = $v; + } + + ++$i; + } + + return null !== $keys ? array_combine($keys, $values) : $values; + } + + /** + * @param string|string[] $needle + */ + public function after(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + { + $str = clone $this; + $i = \PHP_INT_MAX; + + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { + $n = (string) $n; + $j = $this->indexOf($n, $offset); + + if (null !== $j && $j < $i) { + $i = $j; + $str->string = $n; + } + } + + if (\PHP_INT_MAX === $i) { + return $str; + } + + if (!$includeNeedle) { + $i += $str->length(); + } + + return $this->slice($i); + } + + /** + * @param string|string[] $needle + */ + public function afterLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + { + $str = clone $this; + $i = null; + + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { + $n = (string) $n; + $j = $this->indexOfLast($n, $offset); + + if (null !== $j && $j >= $i) { + $i = $offset = $j; + $str->string = $n; + } + } + + if (null === $i) { + return $str; + } + + if (!$includeNeedle) { + $i += $str->length(); + } + + return $this->slice($i); + } + + abstract public function append(string ...$suffix): static; + + /** + * @param string|string[] $needle + */ + public function before(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + { + $str = clone $this; + $i = \PHP_INT_MAX; + + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { + $n = (string) $n; + $j = $this->indexOf($n, $offset); + + if (null !== $j && $j < $i) { + $i = $j; + $str->string = $n; + } + } + + if (\PHP_INT_MAX === $i) { + return $str; + } + + if ($includeNeedle) { + $i += $str->length(); + } + + return $this->slice(0, $i); + } + + /** + * @param string|string[] $needle + */ + public function beforeLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + { + $str = clone $this; + $i = null; + + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { + $n = (string) $n; + $j = $this->indexOfLast($n, $offset); + + if (null !== $j && $j >= $i) { + $i = $offset = $j; + $str->string = $n; + } + } + + if (null === $i) { + return $str; + } + + if ($includeNeedle) { + $i += $str->length(); + } + + return $this->slice(0, $i); + } + + /** + * @return int[] + */ + public function bytesAt(int $offset): array + { + $str = $this->slice($offset, 1); + + return '' === $str->string ? [] : array_values(unpack('C*', $str->string)); + } + + abstract public function camel(): static; + + /** + * @return static[] + */ + abstract public function chunk(int $length = 1): array; + + public function collapseWhitespace(): static + { + $str = clone $this; + $str->string = trim(preg_replace("/(?:[ \n\r\t\x0C]{2,}+|[\n\r\t\x0C])/", ' ', $str->string), " \n\r\t\x0C"); + + return $str; + } + + /** + * @param string|string[] $needle + */ + public function containsAny(string|iterable $needle): bool + { + return null !== $this->indexOf($needle); + } + + /** + * @param string|string[] $suffix + */ + public function endsWith(string|iterable $suffix): bool + { + if (\is_string($suffix)) { + throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); + } + + foreach ($suffix as $s) { + if ($this->endsWith((string) $s)) { + return true; + } + } + + return false; + } + + public function ensureEnd(string $suffix): static + { + if (!$this->endsWith($suffix)) { + return $this->append($suffix); + } + + $suffix = preg_quote($suffix); + $regex = '{('.$suffix.')(?:'.$suffix.')++$}D'; + + return $this->replaceMatches($regex.($this->ignoreCase ? 'i' : ''), '$1'); + } + + public function ensureStart(string $prefix): static + { + $prefix = new static($prefix); + + if (!$this->startsWith($prefix)) { + return $this->prepend($prefix); + } + + $str = clone $this; + $i = $prefixLen = $prefix->length(); + + while ($this->indexOf($prefix, $i) === $i) { + $str = $str->slice($prefixLen); + $i += $prefixLen; + } + + return $str; + } + + /** + * @param string|string[] $string + */ + public function equalsTo(string|iterable $string): bool + { + if (\is_string($string)) { + throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); + } + + foreach ($string as $s) { + if ($this->equalsTo((string) $s)) { + return true; + } + } + + return false; + } + + abstract public function folded(): static; + + public function ignoreCase(): static + { + $str = clone $this; + $str->ignoreCase = true; + + return $str; + } + + /** + * @param string|string[] $needle + */ + public function indexOf(string|iterable $needle, int $offset = 0): ?int + { + if (\is_string($needle)) { + throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); + } + + $i = \PHP_INT_MAX; + + foreach ($needle as $n) { + $j = $this->indexOf((string) $n, $offset); + + if (null !== $j && $j < $i) { + $i = $j; + } + } + + return \PHP_INT_MAX === $i ? null : $i; + } + + /** + * @param string|string[] $needle + */ + public function indexOfLast(string|iterable $needle, int $offset = 0): ?int + { + if (\is_string($needle)) { + throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); + } + + $i = null; + + foreach ($needle as $n) { + $j = $this->indexOfLast((string) $n, $offset); + + if (null !== $j && $j >= $i) { + $i = $offset = $j; + } + } + + return $i; + } + + public function isEmpty(): bool + { + return '' === $this->string; + } + + abstract public function join(array $strings, string $lastGlue = null): static; + + public function jsonSerialize(): string + { + return $this->string; + } + + abstract public function length(): int; + + abstract public function lower(): static; + + /** + * Matches the string using a regular expression. + * + * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression. + * + * @return array All matches in a multi-dimensional array ordered according to flags + */ + abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array; + + abstract public function padBoth(int $length, string $padStr = ' '): static; + + abstract public function padEnd(int $length, string $padStr = ' '): static; + + abstract public function padStart(int $length, string $padStr = ' '): static; + + abstract public function prepend(string ...$prefix): static; + + public function repeat(int $multiplier): static + { + if (0 > $multiplier) { + throw new InvalidArgumentException(sprintf('Multiplier must be positive, %d given.', $multiplier)); + } + + $str = clone $this; + $str->string = str_repeat($str->string, $multiplier); + + return $str; + } + + abstract public function replace(string $from, string $to): static; + + abstract public function replaceMatches(string $fromRegexp, string|callable $to): static; + + abstract public function reverse(): static; + + abstract public function slice(int $start = 0, int $length = null): static; + + abstract public function snake(): static; + + abstract public function splice(string $replacement, int $start = 0, int $length = null): static; + + /** + * @return static[] + */ + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (null === $flags) { + throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); + } + + if ($this->ignoreCase) { + $delimiter .= 'i'; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + if (false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) { + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Splitting failed with '.$k.'.'); + } + } + + throw new RuntimeException('Splitting failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + $str = clone $this; + + if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) { + foreach ($chunks as &$chunk) { + $str->string = $chunk[0]; + $chunk[0] = clone $str; + } + } else { + foreach ($chunks as &$chunk) { + $str->string = $chunk; + $chunk = clone $str; + } + } + + return $chunks; + } + + /** + * @param string|string[] $prefix + */ + public function startsWith(string|iterable $prefix): bool + { + if (\is_string($prefix)) { + throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); + } + + foreach ($prefix as $prefix) { + if ($this->startsWith((string) $prefix)) { + return true; + } + } + + return false; + } + + abstract public function title(bool $allWords = false): static; + + public function toByteString(string $toEncoding = null): ByteString + { + $b = new ByteString(); + + $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], true) ? 'UTF-8' : $toEncoding; + + if (null === $toEncoding || $toEncoding === $fromEncoding = $this instanceof AbstractUnicodeString || preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252') { + $b->string = $this->string; + + return $b; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + try { + $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); + } catch (InvalidArgumentException $e) { + if (!\function_exists('iconv')) { + throw $e; + } + + $b->string = iconv('UTF-8', $toEncoding, $this->string); + } + } finally { + restore_error_handler(); + } + + return $b; + } + + public function toCodePointString(): CodePointString + { + return new CodePointString($this->string); + } + + public function toString(): string + { + return $this->string; + } + + public function toUnicodeString(): UnicodeString + { + return new UnicodeString($this->string); + } + + abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static; + + abstract public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static; + + /** + * @param string|string[] $prefix + */ + public function trimPrefix($prefix): static + { + if (\is_array($prefix) || $prefix instanceof \Traversable) { + foreach ($prefix as $s) { + $t = $this->trimPrefix($s); + + if ($t->string !== $this->string) { + return $t; + } + } + + return clone $this; + } + + $str = clone $this; + + if ($prefix instanceof self) { + $prefix = $prefix->string; + } else { + $prefix = (string) $prefix; + } + + if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) { + $str->string = substr($this->string, \strlen($prefix)); + } + + return $str; + } + + abstract public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static; + + /** + * @param string|string[] $suffix + */ + public function trimSuffix($suffix): static + { + if (\is_array($suffix) || $suffix instanceof \Traversable) { + foreach ($suffix as $s) { + $t = $this->trimSuffix($s); + + if ($t->string !== $this->string) { + return $t; + } + } + + return clone $this; + } + + $str = clone $this; + + if ($suffix instanceof self) { + $suffix = $suffix->string; + } else { + $suffix = (string) $suffix; + } + + if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) { + $str->string = substr($this->string, 0, -\strlen($suffix)); + } + + return $str; + } + + public function truncate(int $length, string $ellipsis = '', bool $cut = true): static + { + $stringLength = $this->length(); + + if ($stringLength <= $length) { + return clone $this; + } + + $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0; + + if ($length < $ellipsisLength) { + $ellipsisLength = 0; + } + + if (!$cut) { + if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) { + return clone $this; + } + + $length += $ellipsisLength; + } + + $str = $this->slice(0, $length - $ellipsisLength); + + return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; + } + + abstract public function upper(): static; + + /** + * Returns the printable length on a terminal. + */ + abstract public function width(bool $ignoreAnsiDecoration = true): int; + + public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): static + { + $lines = '' !== $break ? $this->split($break) : [clone $this]; + $chars = []; + $mask = ''; + + if (1 === \count($lines) && '' === $lines[0]->string) { + return $lines[0]; + } + + foreach ($lines as $i => $line) { + if ($i) { + $chars[] = $break; + $mask .= '#'; + } + + foreach ($line->chunk() as $char) { + $chars[] = $char->string; + $mask .= ' ' === $char->string ? ' ' : '?'; + } + } + + $string = ''; + $j = 0; + $b = $i = -1; + $mask = wordwrap($mask, $width, '#', $cut); + + while (false !== $b = strpos($mask, '#', $b + 1)) { + for (++$i; $i < $b; ++$i) { + $string .= $chars[$j]; + unset($chars[$j++]); + } + + if ($break === $chars[$j] || ' ' === $chars[$j]) { + unset($chars[$j++]); + } + + $string .= $break; + } + + $str = clone $this; + $str->string = $string.implode('', $chars); + + return $str; + } + + public function __sleep(): array + { + return ['string']; + } + + public function __clone() + { + $this->ignoreCase = false; + } + + public function __toString(): string + { + return $this->string; + } +} diff --git a/cacme/vendor/symfony/string/AbstractUnicodeString.php b/cacme/vendor/symfony/string/AbstractUnicodeString.php new file mode 100644 index 0000000..00096df --- /dev/null +++ b/cacme/vendor/symfony/string/AbstractUnicodeString.php @@ -0,0 +1,606 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; +use Symfony\Component\String\Exception\RuntimeException; + +/** + * Represents a string of abstract Unicode characters. + * + * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). + * This class is the abstract type to use as a type-hint when the logic you want to + * implement is Unicode-aware but doesn't care about code points vs grapheme clusters. + * + * @author Nicolas Grekas + * + * @throws ExceptionInterface + */ +abstract class AbstractUnicodeString extends AbstractString +{ + public const NFC = \Normalizer::NFC; + public const NFD = \Normalizer::NFD; + public const NFKC = \Normalizer::NFKC; + public const NFKD = \Normalizer::NFKD; + + // all ASCII letters sorted by typical frequency of occurrence + private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; + + // the subset of folded case mappings that is not in lower case mappings + private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'İ', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; + private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'i̇', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; + + // the subset of upper case mappings that map one code point to many code points + private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; + private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ԵՒ', 'ՄՆ', 'ՄԵ', 'ՄԻ', 'ՎՆ', 'ՄԽ', 'ʼN', 'Ϊ́', 'Ϋ́', 'J̌', 'H̱', 'T̈', 'W̊', 'Y̊', 'Aʾ', 'Υ̓', 'Υ̓̀', 'Υ̓́', 'Υ̓͂', 'Α͂', 'Η͂', 'Ϊ̀', 'Ϊ́', 'Ι͂', 'Ϊ͂', 'Ϋ̀', 'Ϋ́', 'Ρ̓', 'Υ͂', 'Ϋ͂', 'Ω͂']; + + // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD + private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ʼn', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'DŽ', 'Dž', 'dž', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '⦅', '⦆', '。', '、', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆']; + private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))']; + + private static $transliterators = []; + private static $tableZero; + private static $tableWide; + + public static function fromCodePoints(int ...$codes): static + { + $string = ''; + + foreach ($codes as $code) { + if (0x80 > $code %= 0x200000) { + $string .= \chr($code); + } elseif (0x800 > $code) { + $string .= \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $string .= \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $string .= \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + } + + return new static($string); + } + + /** + * Generic UTF-8 to ASCII transliteration. + * + * Install the intl extension for best results. + * + * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs() + */ + public function ascii(array $rules = []): self + { + $str = clone $this; + $s = $str->string; + $str->string = ''; + + array_unshift($rules, 'nfd'); + $rules[] = 'latin-ascii'; + + if (\function_exists('transliterator_transliterate')) { + $rules[] = 'any-latin/bgn'; + } + + $rules[] = 'nfkd'; + $rules[] = '[:nonspacing mark:] remove'; + + while (\strlen($s) - 1 > $i = strspn($s, self::ASCII)) { + if (0 < --$i) { + $str->string .= substr($s, 0, $i); + $s = substr($s, $i); + } + + if (!$rule = array_shift($rules)) { + $rules = []; // An empty rule interrupts the next ones + } + + if ($rule instanceof \Transliterator) { + $s = $rule->transliterate($s); + } elseif ($rule instanceof \Closure) { + $s = $rule($s); + } elseif ($rule) { + if ('nfd' === $rule = strtolower($rule)) { + normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD); + } elseif ('nfkd' === $rule) { + normalizer_is_normalized($s, self::NFKD) ?: $s = normalizer_normalize($s, self::NFKD); + } elseif ('[:nonspacing mark:] remove' === $rule) { + $s = preg_replace('/\p{Mn}++/u', '', $s); + } elseif ('latin-ascii' === $rule) { + $s = str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s); + } elseif ('de-ascii' === $rule) { + $s = preg_replace("/([AUO])\u{0308}(?=\p{Ll})/u", '$1e', $s); + $s = str_replace(["a\u{0308}", "o\u{0308}", "u\u{0308}", "A\u{0308}", "O\u{0308}", "U\u{0308}"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s); + } elseif (\function_exists('transliterator_transliterate')) { + if (null === $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule)) { + if ('any-latin/bgn' === $rule) { + $rule = 'any-latin'; + $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule); + } + + if (null === $transliterator) { + throw new InvalidArgumentException(sprintf('Unknown transliteration rule "%s".', $rule)); + } + + self::$transliterators['any-latin/bgn'] = $transliterator; + } + + $s = $transliterator->transliterate($s); + } + } elseif (!\function_exists('iconv')) { + $s = preg_replace('/[^\x00-\x7F]/u', '?', $s); + } else { + $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) { + $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); + + if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { + throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); + } + + return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); + }, $s); + } + } + + $str->string .= $s; + + return $str; + } + + public function camel(): static + { + $str = clone $this; + $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?![A-Z]{2,})/u', static function ($m) use (&$i) { + return 1 === ++$i ? ('İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8')) : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); + }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string))); + + return $str; + } + + /** + * @return int[] + */ + public function codePointsAt(int $offset): array + { + $str = $this->slice($offset, 1); + + if ('' === $str->string) { + return []; + } + + $codePoints = []; + + foreach (preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { + $codePoints[] = mb_ord($c, 'UTF-8'); + } + + return $codePoints; + } + + public function folded(bool $compat = true): static + { + $str = clone $this; + + if (!$compat || !\defined('Normalizer::NFKC_CF')) { + $str->string = normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC); + $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8'); + } else { + $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF); + } + + return $str; + } + + public function join(array $strings, string $lastGlue = null): static + { + $str = clone $this; + + $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; + $str->string = implode($this->string, $strings).$tail; + + if (!preg_match('//u', $str->string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function lower(): static + { + $str = clone $this; + $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8'); + + return $str; + } + + public function match(string $regexp, int $flags = 0, int $offset = 0): array + { + $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; + + if ($this->ignoreCase) { + $regexp .= 'i'; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + if (false === $match($regexp.'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + return $matches; + } + + public function normalize(int $form = self::NFC): static + { + if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) { + throw new InvalidArgumentException('Unsupported normalization form.'); + } + + $str = clone $this; + normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); + + return $str; + } + + public function padBoth(int $length, string $padStr = ' '): static + { + if ('' === $padStr || !preg_match('//u', $padStr)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $pad = clone $this; + $pad->string = $padStr; + + return $this->pad($length, $pad, \STR_PAD_BOTH); + } + + public function padEnd(int $length, string $padStr = ' '): static + { + if ('' === $padStr || !preg_match('//u', $padStr)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $pad = clone $this; + $pad->string = $padStr; + + return $this->pad($length, $pad, \STR_PAD_RIGHT); + } + + public function padStart(int $length, string $padStr = ' '): static + { + if ('' === $padStr || !preg_match('//u', $padStr)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $pad = clone $this; + $pad->string = $padStr; + + return $this->pad($length, $pad, \STR_PAD_LEFT); + } + + public function replaceMatches(string $fromRegexp, string|callable $to): static + { + if ($this->ignoreCase) { + $fromRegexp .= 'i'; + } + + if (\is_array($to) || $to instanceof \Closure) { + $replace = 'preg_replace_callback'; + $to = static function (array $m) use ($to): string { + $to = $to($m); + + if ('' !== $to && (!\is_string($to) || !preg_match('//u', $to))) { + throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.'); + } + + return $to; + }; + } elseif ('' !== $to && !preg_match('//u', $to)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } else { + $replace = 'preg_replace'; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + if (null === $string = $replace($fromRegexp.'u', $to, $this->string)) { + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + $str = clone $this; + $str->string = $string; + + return $str; + } + + public function reverse(): static + { + $str = clone $this; + $str->string = implode('', array_reverse(preg_split('/(\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY))); + + return $str; + } + + public function snake(): static + { + $str = $this->camel(); + $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8'); + + return $str; + } + + public function title(bool $allWords = false): static + { + $str = clone $this; + + $limit = $allWords ? -1 : 1; + + $str->string = preg_replace_callback('/\b./u', static function (array $m): string { + return mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); + }, $str->string, $limit); + + return $str; + } + + public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static + { + if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { + throw new InvalidArgumentException('Invalid UTF-8 chars.'); + } + $chars = preg_quote($chars); + + $str = clone $this; + $str->string = preg_replace("{^[$chars]++|[$chars]++$}uD", '', $str->string); + + return $str; + } + + public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static + { + if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { + throw new InvalidArgumentException('Invalid UTF-8 chars.'); + } + $chars = preg_quote($chars); + + $str = clone $this; + $str->string = preg_replace("{[$chars]++$}uD", '', $str->string); + + return $str; + } + + public function trimPrefix($prefix): static + { + if (!$this->ignoreCase) { + return parent::trimPrefix($prefix); + } + + $str = clone $this; + + if ($prefix instanceof \Traversable) { + $prefix = iterator_to_array($prefix, false); + } elseif ($prefix instanceof parent) { + $prefix = $prefix->string; + } + + $prefix = implode('|', array_map('preg_quote', (array) $prefix)); + $str->string = preg_replace("{^(?:$prefix)}iuD", '', $this->string); + + return $str; + } + + public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static + { + if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { + throw new InvalidArgumentException('Invalid UTF-8 chars.'); + } + $chars = preg_quote($chars); + + $str = clone $this; + $str->string = preg_replace("{^[$chars]++}uD", '', $str->string); + + return $str; + } + + public function trimSuffix($suffix): static + { + if (!$this->ignoreCase) { + return parent::trimSuffix($suffix); + } + + $str = clone $this; + + if ($suffix instanceof \Traversable) { + $suffix = iterator_to_array($suffix, false); + } elseif ($suffix instanceof parent) { + $suffix = $suffix->string; + } + + $suffix = implode('|', array_map('preg_quote', (array) $suffix)); + $str->string = preg_replace("{(?:$suffix)$}iuD", '', $this->string); + + return $str; + } + + public function upper(): static + { + $str = clone $this; + $str->string = mb_strtoupper($str->string, 'UTF-8'); + + return $str; + } + + public function width(bool $ignoreAnsiDecoration = true): int + { + $width = 0; + $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string); + + if (false !== strpos($s, "\r")) { + $s = str_replace(["\r\n", "\r"], "\n", $s); + } + + if (!$ignoreAnsiDecoration) { + $s = preg_replace('/[\p{Cc}\x7F]++/u', '', $s); + } + + foreach (explode("\n", $s) as $s) { + if ($ignoreAnsiDecoration) { + $s = preg_replace('/(?:\x1B(?: + \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [\x40-\x7E] + | [P\]X^_] .*? \x1B\\\\ + | [\x41-\x7E] + )|[\p{Cc}\x7F]++)/xu', '', $s); + } + + $lineWidth = $this->wcswidth($s); + + if ($lineWidth > $width) { + $width = $lineWidth; + } + } + + return $width; + } + + private function pad(int $len, self $pad, int $type): static + { + $sLen = $this->length(); + + if ($len <= $sLen) { + return clone $this; + } + + $padLen = $pad->length(); + $freeLen = $len - $sLen; + $len = $freeLen % $padLen; + + switch ($type) { + case \STR_PAD_RIGHT: + return $this->append(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + case \STR_PAD_LEFT: + return $this->prepend(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + case \STR_PAD_BOTH: + $freeLen /= 2; + + $rightLen = ceil($freeLen); + $len = $rightLen % $padLen; + $str = $this->append(str_repeat($pad->string, intdiv($rightLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + $leftLen = floor($freeLen); + $len = $leftLen % $padLen; + + return $str->prepend(str_repeat($pad->string, intdiv($leftLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + default: + throw new InvalidArgumentException('Invalid padding type.'); + } + } + + /** + * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. + */ + private function wcswidth(string $string): int + { + $width = 0; + + foreach (preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { + $codePoint = mb_ord($c, 'UTF-8'); + + if (0 === $codePoint // NULL + || 0x034F === $codePoint // COMBINING GRAPHEME JOINER + || (0x200B <= $codePoint && 0x200F >= $codePoint) // ZERO WIDTH SPACE to RIGHT-TO-LEFT MARK + || 0x2028 === $codePoint // LINE SEPARATOR + || 0x2029 === $codePoint // PARAGRAPH SEPARATOR + || (0x202A <= $codePoint && 0x202E >= $codePoint) // LEFT-TO-RIGHT EMBEDDING to RIGHT-TO-LEFT OVERRIDE + || (0x2060 <= $codePoint && 0x2063 >= $codePoint) // WORD JOINER to INVISIBLE SEPARATOR + ) { + continue; + } + + // Non printable characters + if (32 > $codePoint // C0 control characters + || (0x07F <= $codePoint && 0x0A0 > $codePoint) // C1 control characters and DEL + ) { + return -1; + } + + if (null === self::$tableZero) { + self::$tableZero = require __DIR__.'/Resources/data/wcswidth_table_zero.php'; + } + + if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) { + $lbound = 0; + while ($ubound >= $lbound) { + $mid = floor(($lbound + $ubound) / 2); + + if ($codePoint > self::$tableZero[$mid][1]) { + $lbound = $mid + 1; + } elseif ($codePoint < self::$tableZero[$mid][0]) { + $ubound = $mid - 1; + } else { + continue 2; + } + } + } + + if (null === self::$tableWide) { + self::$tableWide = require __DIR__.'/Resources/data/wcswidth_table_wide.php'; + } + + if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) { + $lbound = 0; + while ($ubound >= $lbound) { + $mid = floor(($lbound + $ubound) / 2); + + if ($codePoint > self::$tableWide[$mid][1]) { + $lbound = $mid + 1; + } elseif ($codePoint < self::$tableWide[$mid][0]) { + $ubound = $mid - 1; + } else { + $width += 2; + + continue 2; + } + } + } + + ++$width; + } + + return $width; + } +} diff --git a/cacme/vendor/symfony/string/ByteString.php b/cacme/vendor/symfony/string/ByteString.php new file mode 100644 index 0000000..639d643 --- /dev/null +++ b/cacme/vendor/symfony/string/ByteString.php @@ -0,0 +1,493 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; +use Symfony\Component\String\Exception\RuntimeException; + +/** + * Represents a binary-safe string of bytes. + * + * @author Nicolas Grekas + * @author Hugo Hamon + * + * @throws ExceptionInterface + */ +class ByteString extends AbstractString +{ + private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + + public function __construct(string $string = '') + { + $this->string = $string; + } + + /* + * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) + * + * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 + * + * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). + * + * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) + */ + + public static function fromRandom(int $length = 16, string $alphabet = null): self + { + if ($length <= 0) { + throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length)); + } + + $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC; + $alphabetSize = \strlen($alphabet); + $bits = (int) ceil(log($alphabetSize, 2.0)); + if ($bits <= 0 || $bits > 56) { + throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.'); + } + + $ret = ''; + while ($length > 0) { + $urandomLength = (int) ceil(2 * $length * $bits / 8.0); + $data = random_bytes($urandomLength); + $unpackedData = 0; + $unpackedBits = 0; + for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { + // Unpack 8 bits + $unpackedData = ($unpackedData << 8) | \ord($data[$i]); + $unpackedBits += 8; + + // While we have enough bits to select a character from the alphabet, keep + // consuming the random data + for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { + $index = ($unpackedData & ((1 << $bits) - 1)); + $unpackedData >>= $bits; + // Unfortunately, the alphabet size is not necessarily a power of two. + // Worst case, it is 2^k + 1, which means we need (k+1) bits and we + // have around a 50% chance of missing as k gets larger + if ($index < $alphabetSize) { + $ret .= $alphabet[$index]; + --$length; + } + } + } + } + + return new static($ret); + } + + public function bytesAt(int $offset): array + { + $str = $this->string[$offset] ?? ''; + + return '' === $str ? [] : [\ord($str)]; + } + + public function append(string ...$suffix): static + { + $str = clone $this; + $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); + + return $str; + } + + public function camel(): static + { + $str = clone $this; + + $parts = explode(' ', trim(ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string)))); + $parts[0] = 1 !== \strlen($parts[0]) && ctype_upper($parts[0]) ? $parts[0] : lcfirst($parts[0]); + $str->string = implode('', $parts); + + return $str; + } + + public function chunk(int $length = 1): array + { + if (1 > $length) { + throw new InvalidArgumentException('The chunk length must be greater than zero.'); + } + + if ('' === $this->string) { + return []; + } + + $str = clone $this; + $chunks = []; + + foreach (str_split($this->string, $length) as $chunk) { + $str->string = $chunk; + $chunks[] = clone $str; + } + + return $chunks; + } + + public function endsWith(string|iterable|AbstractString $suffix): bool + { + if ($suffix instanceof AbstractString) { + $suffix = $suffix->string; + } elseif (!\is_string($suffix)) { + return parent::endsWith($suffix); + } + + return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); + } + + public function equalsTo(string|iterable|AbstractString $string): bool + { + if ($string instanceof AbstractString) { + $string = $string->string; + } elseif (!\is_string($string)) { + return parent::equalsTo($string); + } + + if ('' !== $string && $this->ignoreCase) { + return 0 === strcasecmp($string, $this->string); + } + + return $string === $this->string; + } + + public function folded(): static + { + $str = clone $this; + $str->string = strtolower($str->string); + + return $str; + } + + public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (!\is_string($needle)) { + return parent::indexOf($needle, $offset); + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset); + + return false === $i ? null : $i; + } + + public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (!\is_string($needle)) { + return parent::indexOfLast($needle, $offset); + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset); + + return false === $i ? null : $i; + } + + public function isUtf8(): bool + { + return '' === $this->string || preg_match('//u', $this->string); + } + + public function join(array $strings, string $lastGlue = null): static + { + $str = clone $this; + + $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; + $str->string = implode($this->string, $strings).$tail; + + return $str; + } + + public function length(): int + { + return \strlen($this->string); + } + + public function lower(): static + { + $str = clone $this; + $str->string = strtolower($str->string); + + return $str; + } + + public function match(string $regexp, int $flags = 0, int $offset = 0): array + { + $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; + + if ($this->ignoreCase) { + $regexp .= 'i'; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + if (false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + return $matches; + } + + public function padBoth(int $length, string $padStr = ' '): static + { + $str = clone $this; + $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); + + return $str; + } + + public function padEnd(int $length, string $padStr = ' '): static + { + $str = clone $this; + $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); + + return $str; + } + + public function padStart(int $length, string $padStr = ' '): static + { + $str = clone $this; + $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); + + return $str; + } + + public function prepend(string ...$prefix): static + { + $str = clone $this; + $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string; + + return $str; + } + + public function replace(string $from, string $to): static + { + $str = clone $this; + + if ('' !== $from) { + $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string); + } + + return $str; + } + + public function replaceMatches(string $fromRegexp, string|callable $to): static + { + if ($this->ignoreCase) { + $fromRegexp .= 'i'; + } + + $replace = \is_array($to) || $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + if (null === $string = $replace($fromRegexp, $to, $this->string)) { + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + $str = clone $this; + $str->string = $string; + + return $str; + } + + public function reverse(): static + { + $str = clone $this; + $str->string = strrev($str->string); + + return $str; + } + + public function slice(int $start = 0, int $length = null): static + { + $str = clone $this; + $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX); + + return $str; + } + + public function snake(): static + { + $str = $this->camel(); + $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string)); + + return $str; + } + + public function splice(string $replacement, int $start = 0, int $length = null): static + { + $str = clone $this; + $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); + + return $str; + } + + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (1 > $limit = $limit ?? \PHP_INT_MAX) { + throw new InvalidArgumentException('Split limit must be a positive integer.'); + } + + if ('' === $delimiter) { + throw new InvalidArgumentException('Split delimiter is empty.'); + } + + if (null !== $flags) { + return parent::split($delimiter, $limit, $flags); + } + + $str = clone $this; + $chunks = $this->ignoreCase + ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit) + : explode($delimiter, $this->string, $limit); + + foreach ($chunks as &$chunk) { + $str->string = $chunk; + $chunk = clone $str; + } + + return $chunks; + } + + public function startsWith(string|iterable|AbstractString $prefix): bool + { + if ($prefix instanceof AbstractString) { + $prefix = $prefix->string; + } elseif (!\is_string($prefix)) { + return parent::startsWith($prefix); + } + + return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix))); + } + + public function title(bool $allWords = false): static + { + $str = clone $this; + $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string); + + return $str; + } + + public function toUnicodeString(string $fromEncoding = null): UnicodeString + { + return new UnicodeString($this->toCodePointString($fromEncoding)->string); + } + + public function toCodePointString(string $fromEncoding = null): CodePointString + { + $u = new CodePointString(); + + if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) { + $u->string = $this->string; + + return $u; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + try { + $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true); + } catch (InvalidArgumentException $e) { + if (!\function_exists('iconv')) { + throw $e; + } + + $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); + + return $u; + } + } finally { + restore_error_handler(); + } + + if (!$validEncoding) { + throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); + } + + $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); + + return $u; + } + + public function trim(string $chars = " \t\n\r\0\x0B\x0C"): static + { + $str = clone $this; + $str->string = trim($str->string, $chars); + + return $str; + } + + public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): static + { + $str = clone $this; + $str->string = rtrim($str->string, $chars); + + return $str; + } + + public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): static + { + $str = clone $this; + $str->string = ltrim($str->string, $chars); + + return $str; + } + + public function upper(): static + { + $str = clone $this; + $str->string = strtoupper($str->string); + + return $str; + } + + public function width(bool $ignoreAnsiDecoration = true): int + { + $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string); + + return (new CodePointString($string))->width($ignoreAnsiDecoration); + } +} diff --git a/cacme/vendor/symfony/string/CHANGELOG.md b/cacme/vendor/symfony/string/CHANGELOG.md new file mode 100644 index 0000000..53af364 --- /dev/null +++ b/cacme/vendor/symfony/string/CHANGELOG.md @@ -0,0 +1,35 @@ +CHANGELOG +========= + +5.4 +--- + + * Add `trimSuffix()` and `trimPrefix()` methods + +5.3 +--- + + * Made `AsciiSlugger` fallback to parent locale's symbolsMap + +5.2.0 +----- + + * added a `FrenchInflector` class + +5.1.0 +----- + + * added the `AbstractString::reverse()` method + * made `AbstractString::width()` follow POSIX.1-2001 + * added `LazyString` which provides memoizing stringable objects + * The component is not marked as `@experimental` anymore + * added the `s()` helper method to get either an `UnicodeString` or `ByteString` instance, + depending of the input string UTF-8 compliancy + * added `$cut` parameter to `Symfony\Component\String\AbstractString::truncate()` + * added `AbstractString::containsAny()` + * allow passing a string of custom characters to `ByteString::fromRandom()` + +5.0.0 +----- + + * added the component as experimental diff --git a/cacme/vendor/symfony/string/CodePointString.php b/cacme/vendor/symfony/string/CodePointString.php new file mode 100644 index 0000000..926ff79 --- /dev/null +++ b/cacme/vendor/symfony/string/CodePointString.php @@ -0,0 +1,260 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; + +/** + * Represents a string of Unicode code points encoded as UTF-8. + * + * @author Nicolas Grekas + * @author Hugo Hamon + * + * @throws ExceptionInterface + */ +class CodePointString extends AbstractUnicodeString +{ + public function __construct(string $string = '') + { + if ('' !== $string && !preg_match('//u', $string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $this->string = $string; + } + + public function append(string ...$suffix): static + { + $str = clone $this; + $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); + + if (!preg_match('//u', $str->string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function chunk(int $length = 1): array + { + if (1 > $length) { + throw new InvalidArgumentException('The chunk length must be greater than zero.'); + } + + if ('' === $this->string) { + return []; + } + + $rx = '/('; + while (65535 < $length) { + $rx .= '.{65535}'; + $length -= 65535; + } + $rx .= '.{'.$length.'})/us'; + + $str = clone $this; + $chunks = []; + + foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { + $str->string = $chunk; + $chunks[] = clone $str; + } + + return $chunks; + } + + public function codePointsAt(int $offset): array + { + $str = $offset ? $this->slice($offset, 1) : $this; + + return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')]; + } + + public function endsWith(string|iterable|AbstractString $suffix): bool + { + if ($suffix instanceof AbstractString) { + $suffix = $suffix->string; + } elseif (!\is_string($suffix)) { + return parent::endsWith($suffix); + } + + if ('' === $suffix || !preg_match('//u', $suffix)) { + return false; + } + + if ($this->ignoreCase) { + return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string); + } + + return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix)); + } + + public function equalsTo(string|iterable|AbstractString $string): bool + { + if ($string instanceof AbstractString) { + $string = $string->string; + } elseif (!\is_string($string)) { + return parent::equalsTo($string); + } + + if ('' !== $string && $this->ignoreCase) { + return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); + } + + return $string === $this->string; + } + + public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (!\is_string($needle)) { + return parent::indexOf($needle, $offset); + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8'); + + return false === $i ? null : $i; + } + + public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (!\is_string($needle)) { + return parent::indexOfLast($needle, $offset); + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8'); + + return false === $i ? null : $i; + } + + public function length(): int + { + return mb_strlen($this->string, 'UTF-8'); + } + + public function prepend(string ...$prefix): static + { + $str = clone $this; + $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; + + if (!preg_match('//u', $str->string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function replace(string $from, string $to): static + { + $str = clone $this; + + if ('' === $from || !preg_match('//u', $from)) { + return $str; + } + + if ('' !== $to && !preg_match('//u', $to)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + if ($this->ignoreCase) { + $str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string)); + } else { + $str->string = str_replace($from, $to, $this->string); + } + + return $str; + } + + public function slice(int $start = 0, int $length = null): static + { + $str = clone $this; + $str->string = mb_substr($this->string, $start, $length, 'UTF-8'); + + return $str; + } + + public function splice(string $replacement, int $start = 0, int $length = null): static + { + if (!preg_match('//u', $replacement)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $str = clone $this; + $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0; + $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length; + $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); + + return $str; + } + + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (1 > $limit = $limit ?? \PHP_INT_MAX) { + throw new InvalidArgumentException('Split limit must be a positive integer.'); + } + + if ('' === $delimiter) { + throw new InvalidArgumentException('Split delimiter is empty.'); + } + + if (null !== $flags) { + return parent::split($delimiter.'u', $limit, $flags); + } + + if (!preg_match('//u', $delimiter)) { + throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); + } + + $str = clone $this; + $chunks = $this->ignoreCase + ? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit) + : explode($delimiter, $this->string, $limit); + + foreach ($chunks as &$chunk) { + $str->string = $chunk; + $chunk = clone $str; + } + + return $chunks; + } + + public function startsWith(string|iterable|AbstractString $prefix): bool + { + if ($prefix instanceof AbstractString) { + $prefix = $prefix->string; + } elseif (!\is_string($prefix)) { + return parent::startsWith($prefix); + } + + if ('' === $prefix || !preg_match('//u', $prefix)) { + return false; + } + + if ($this->ignoreCase) { + return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8'); + } + + return 0 === strncmp($this->string, $prefix, \strlen($prefix)); + } +} diff --git a/cacme/vendor/symfony/string/Exception/ExceptionInterface.php b/cacme/vendor/symfony/string/Exception/ExceptionInterface.php new file mode 100644 index 0000000..3619786 --- /dev/null +++ b/cacme/vendor/symfony/string/Exception/ExceptionInterface.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 Symfony\Component\String\Exception; + +interface ExceptionInterface extends \Throwable +{ +} diff --git a/cacme/vendor/symfony/string/Exception/InvalidArgumentException.php b/cacme/vendor/symfony/string/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..6aa586b --- /dev/null +++ b/cacme/vendor/symfony/string/Exception/InvalidArgumentException.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 Symfony\Component\String\Exception; + +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/string/Exception/RuntimeException.php b/cacme/vendor/symfony/string/Exception/RuntimeException.php new file mode 100644 index 0000000..77cb091 --- /dev/null +++ b/cacme/vendor/symfony/string/Exception/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 Symfony\Component\String\Exception; + +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/cacme/vendor/symfony/string/Inflector/EnglishInflector.php b/cacme/vendor/symfony/string/Inflector/EnglishInflector.php new file mode 100644 index 0000000..9f2fac6 --- /dev/null +++ b/cacme/vendor/symfony/string/Inflector/EnglishInflector.php @@ -0,0 +1,511 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Inflector; + +final class EnglishInflector implements InflectorInterface +{ + /** + * Map English plural to singular suffixes. + * + * @see http://english-zone.com/spelling/plurals.html + */ + private const PLURAL_MAP = [ + // First entry: plural suffix, reversed + // Second entry: length of plural suffix + // Third entry: Whether the suffix may succeed a vocal + // Fourth entry: Whether the suffix may succeed a consonant + // Fifth entry: singular suffix, normal + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['a', 1, true, true, ['on', 'um']], + + // nebulae (nebula) + ['ea', 2, true, true, 'a'], + + // services (service) + ['secivres', 8, true, true, 'service'], + + // mice (mouse), lice (louse) + ['eci', 3, false, true, 'ouse'], + + // geese (goose) + ['esee', 4, false, true, 'oose'], + + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) + ['i', 1, true, true, 'us'], + + // men (man), women (woman) + ['nem', 3, true, true, 'man'], + + // children (child) + ['nerdlihc', 8, true, true, 'child'], + + // oxen (ox) + ['nexo', 4, false, false, 'ox'], + + // indices (index), appendices (appendix), prices (price) + ['seci', 4, false, true, ['ex', 'ix', 'ice']], + + // selfies (selfie) + ['seifles', 7, true, true, 'selfie'], + + // zombies (zombie) + ['seibmoz', 7, true, true, 'zombie'], + + // movies (movie) + ['seivom', 6, true, true, 'movie'], + + // conspectuses (conspectus), prospectuses (prospectus) + ['sesutcep', 8, true, true, 'pectus'], + + // feet (foot) + ['teef', 4, true, true, 'foot'], + + // geese (goose) + ['eseeg', 5, true, true, 'goose'], + + // teeth (tooth) + ['hteet', 5, true, true, 'tooth'], + + // news (news) + ['swen', 4, true, true, 'news'], + + // series (series) + ['seires', 6, true, true, 'series'], + + // babies (baby) + ['sei', 3, false, true, 'y'], + + // accesses (access), addresses (address), kisses (kiss) + ['sess', 4, true, false, 'ss'], + + // analyses (analysis), ellipses (ellipsis), fungi (fungus), + // neuroses (neurosis), theses (thesis), emphases (emphasis), + // oases (oasis), crises (crisis), houses (house), bases (base), + // atlases (atlas) + ['ses', 3, true, true, ['s', 'se', 'sis']], + + // objectives (objective), alternative (alternatives) + ['sevit', 5, true, true, 'tive'], + + // drives (drive) + ['sevird', 6, false, true, 'drive'], + + // lives (life), wives (wife) + ['sevi', 4, false, true, 'ife'], + + // moves (move) + ['sevom', 5, true, true, 'move'], + + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) + ['sev', 3, true, true, ['f', 've', 'ff']], + + // axes (axis), axes (ax), axes (axe) + ['sexa', 4, false, false, ['ax', 'axe', 'axis']], + + // indexes (index), matrixes (matrix) + ['sex', 3, true, false, 'x'], + + // quizzes (quiz) + ['sezz', 4, true, false, 'z'], + + // bureaus (bureau) + ['suae', 4, false, true, 'eau'], + + // fees (fee), trees (tree), employees (employee) + ['see', 3, true, true, 'ee'], + + // edges (edge) + ['segd', 4, true, true, 'dge'], + + // roses (rose), garages (garage), cassettes (cassette), + // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), + // shoes (shoe) + ['se', 2, true, true, ['', 'e']], + + // tags (tag) + ['s', 1, true, true, ''], + + // chateaux (chateau) + ['xuae', 4, false, true, 'eau'], + + // people (person) + ['elpoep', 6, true, true, 'person'], + ]; + + /** + * Map English singular to plural suffixes. + * + * @see http://english-zone.com/spelling/plurals.html + */ + private const SINGULAR_MAP = [ + // First entry: singular suffix, reversed + // Second entry: length of singular suffix + // Third entry: Whether the suffix may succeed a vocal + // Fourth entry: Whether the suffix may succeed a consonant + // Fifth entry: plural suffix, normal + + // criterion (criteria) + ['airetirc', 8, false, false, 'criterion'], + + // nebulae (nebula) + ['aluben', 6, false, false, 'nebulae'], + + // children (child) + ['dlihc', 5, true, true, 'children'], + + // prices (price) + ['eci', 3, false, true, 'ices'], + + // services (service) + ['ecivres', 7, true, true, 'services'], + + // lives (life), wives (wife) + ['efi', 3, false, true, 'ives'], + + // selfies (selfie) + ['eifles', 6, true, true, 'selfies'], + + // movies (movie) + ['eivom', 5, true, true, 'movies'], + + // lice (louse) + ['esuol', 5, false, true, 'lice'], + + // mice (mouse) + ['esuom', 5, false, true, 'mice'], + + // geese (goose) + ['esoo', 4, false, true, 'eese'], + + // houses (house), bases (base) + ['es', 2, true, true, 'ses'], + + // geese (goose) + ['esoog', 5, true, true, 'geese'], + + // caves (cave) + ['ev', 2, true, true, 'ves'], + + // drives (drive) + ['evird', 5, false, true, 'drives'], + + // objectives (objective), alternative (alternatives) + ['evit', 4, true, true, 'tives'], + + // moves (move) + ['evom', 4, true, true, 'moves'], + + // staves (staff) + ['ffats', 5, true, true, 'staves'], + + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) + ['ff', 2, true, true, 'ffs'], + + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) + ['f', 1, true, true, ['fs', 'ves']], + + // arches (arch) + ['hc', 2, true, true, 'ches'], + + // bushes (bush) + ['hs', 2, true, true, 'shes'], + + // teeth (tooth) + ['htoot', 5, true, true, 'teeth'], + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['mu', 2, true, true, 'a'], + + // men (man), women (woman) + ['nam', 3, true, true, 'men'], + + // people (person) + ['nosrep', 6, true, true, ['persons', 'people']], + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['noi', 3, true, true, 'ions'], + + // coupon (coupons) + ['nop', 3, true, true, 'pons'], + + // seasons (season), treasons (treason), poisons (poison), lessons (lesson) + ['nos', 3, true, true, 'sons'], + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['no', 2, true, true, 'a'], + + // echoes (echo) + ['ohce', 4, true, true, 'echoes'], + + // heroes (hero) + ['oreh', 4, true, true, 'heroes'], + + // atlases (atlas) + ['salta', 5, true, true, 'atlases'], + + // irises (iris) + ['siri', 4, true, true, 'irises'], + + // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) + // theses (thesis), emphases (emphasis), oases (oasis), + // crises (crisis) + ['sis', 3, true, true, 'ses'], + + // accesses (access), addresses (address), kisses (kiss) + ['ss', 2, true, false, 'sses'], + + // syllabi (syllabus) + ['suballys', 8, true, true, 'syllabi'], + + // buses (bus) + ['sub', 3, true, true, 'buses'], + + // circuses (circus) + ['suc', 3, true, true, 'cuses'], + + // conspectuses (conspectus), prospectuses (prospectus) + ['sutcep', 6, true, true, 'pectuses'], + + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) + ['su', 2, true, true, 'i'], + + // news (news) + ['swen', 4, true, true, 'news'], + + // feet (foot) + ['toof', 4, true, true, 'feet'], + + // chateaux (chateau), bureaus (bureau) + ['uae', 3, false, true, ['eaus', 'eaux']], + + // oxen (ox) + ['xo', 2, false, false, 'oxen'], + + // hoaxes (hoax) + ['xaoh', 4, true, false, 'hoaxes'], + + // indices (index) + ['xedni', 5, false, true, ['indicies', 'indexes']], + + // boxes (box) + ['xo', 2, false, true, 'oxes'], + + // indexes (index), matrixes (matrix) + ['x', 1, true, false, ['cies', 'xes']], + + // appendices (appendix) + ['xi', 2, false, true, 'ices'], + + // babies (baby) + ['y', 1, false, true, 'ies'], + + // quizzes (quiz) + ['ziuq', 4, true, false, 'quizzes'], + + // waltzes (waltz) + ['z', 1, true, true, 'zes'], + ]; + + /** + * A list of words which should not be inflected, reversed. + */ + private const UNINFLECTED = [ + '', + + // data + 'atad', + + // deer + 'reed', + + // feedback + 'kcabdeef', + + // fish + 'hsif', + + // info + 'ofni', + + // moose + 'esoom', + + // series + 'seires', + + // sheep + 'peehs', + + // species + 'seiceps', + ]; + + /** + * {@inheritdoc} + */ + public function singularize(string $plural): array + { + $pluralRev = strrev($plural); + $lowerPluralRev = strtolower($pluralRev); + $pluralLength = \strlen($lowerPluralRev); + + // Check if the word is one which is not inflected, return early if so + if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) { + return [$plural]; + } + + // The outer loop iterates over the entries of the plural table + // The inner loop $j iterates over the characters of the plural suffix + // in the plural table to compare them with the characters of the actual + // given plural suffix + foreach (self::PLURAL_MAP as $map) { + $suffix = $map[0]; + $suffixLength = $map[1]; + $j = 0; + + // Compare characters in the plural table and of the suffix of the + // given plural one by one + while ($suffix[$j] === $lowerPluralRev[$j]) { + // Let $j point to the next character + ++$j; + + // Successfully compared the last character + // Add an entry with the singular suffix to the singular array + if ($j === $suffixLength) { + // Is there any character preceding the suffix in the plural string? + if ($j < $pluralLength) { + $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); + + if (!$map[2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one + break; + } + + if (!$map[3] && !$nextIsVocal) { + // suffix may not succeed a consonant but next char is one + break; + } + } + + $newBase = substr($plural, 0, $pluralLength - $suffixLength); + $newSuffix = $map[4]; + + // Check whether the first character in the plural suffix + // is uppercased. If yes, uppercase the first character in + // the singular suffix too + $firstUpper = ctype_upper($pluralRev[$j - 1]); + + if (\is_array($newSuffix)) { + $singulars = []; + + foreach ($newSuffix as $newSuffixEntry) { + $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); + } + + return $singulars; + } + + return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; + } + + // Suffix is longer than word + if ($j === $pluralLength) { + break; + } + } + } + + // Assume that plural and singular is identical + return [$plural]; + } + + /** + * {@inheritdoc} + */ + public function pluralize(string $singular): array + { + $singularRev = strrev($singular); + $lowerSingularRev = strtolower($singularRev); + $singularLength = \strlen($lowerSingularRev); + + // Check if the word is one which is not inflected, return early if so + if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) { + return [$singular]; + } + + // The outer loop iterates over the entries of the singular table + // The inner loop $j iterates over the characters of the singular suffix + // in the singular table to compare them with the characters of the actual + // given singular suffix + foreach (self::SINGULAR_MAP as $map) { + $suffix = $map[0]; + $suffixLength = $map[1]; + $j = 0; + + // Compare characters in the singular table and of the suffix of the + // given plural one by one + + while ($suffix[$j] === $lowerSingularRev[$j]) { + // Let $j point to the next character + ++$j; + + // Successfully compared the last character + // Add an entry with the plural suffix to the plural array + if ($j === $suffixLength) { + // Is there any character preceding the suffix in the plural string? + if ($j < $singularLength) { + $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); + + if (!$map[2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one + break; + } + + if (!$map[3] && !$nextIsVocal) { + // suffix may not succeed a consonant but next char is one + break; + } + } + + $newBase = substr($singular, 0, $singularLength - $suffixLength); + $newSuffix = $map[4]; + + // Check whether the first character in the singular suffix + // is uppercased. If yes, uppercase the first character in + // the singular suffix too + $firstUpper = ctype_upper($singularRev[$j - 1]); + + if (\is_array($newSuffix)) { + $plurals = []; + + foreach ($newSuffix as $newSuffixEntry) { + $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); + } + + return $plurals; + } + + return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; + } + + // Suffix is longer than word + if ($j === $singularLength) { + break; + } + } + } + + // Assume that plural is singular with a trailing `s` + return [$singular.'s']; + } +} diff --git a/cacme/vendor/symfony/string/Inflector/FrenchInflector.php b/cacme/vendor/symfony/string/Inflector/FrenchInflector.php new file mode 100644 index 0000000..612c8f2 --- /dev/null +++ b/cacme/vendor/symfony/string/Inflector/FrenchInflector.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\Component\String\Inflector; + +/** + * French inflector. + * + * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix". + */ +final class FrenchInflector implements InflectorInterface +{ + /** + * A list of all rules for pluralise. + * + * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php + */ + private const PLURALIZE_REGEXP = [ + // First entry: regexp + // Second entry: replacement + + // Words finishing with "s", "x" or "z" are invariables + // Les mots finissant par "s", "x" ou "z" sont invariables + ['/(s|x|z)$/i', '\1'], + + // Words finishing with "eau" are pluralized with a "x" + // Les mots finissant par "eau" prennent tous un "x" au pluriel + ['/(eau)$/i', '\1x'], + + // Words finishing with "au" are pluralized with a "x" excepted "landau" + // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" + ['/^(landau)$/i', '\1s'], + ['/(au)$/i', '\1x'], + + // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" + // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" + ['/^(pneu|bleu|émeu)$/i', '\1s'], + ['/(eu)$/i', '\1x'], + + // Words finishing with "al" are pluralized with a "aux" excepted + // Les mots finissant en "al" se terminent en "aux" sauf + ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'], + ['/al$/i', '\1aux'], + + // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux + ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'], + + // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel + ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'], + + // Invariable words + ['/^(cinquante|soixante|mille)$/i', '\1'], + + // French titles + ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'], + ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'], + ]; + + /** + * A list of all rules for singularize. + */ + private const SINGULARIZE_REGEXP = [ + // First entry: regexp + // Second entry: replacement + + // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux + ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'], + + // Words finishing with "eau" are pluralized with a "x" + // Les mots finissant par "eau" prennent tous un "x" au pluriel + ['/(eau)x$/i', '\1'], + + // Words finishing with "al" are pluralized with a "aux" expected + // Les mots finissant en "al" se terminent en "aux" sauf + ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'], + + // Words finishing with "au" are pluralized with a "x" excepted "landau" + // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" + ['/(au)x$/i', '\1'], + + // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" + // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" + ['/(eu)x$/i', '\1'], + + // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou + // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou + ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'], + + // French titles + ['/^mes(dame|demoiselle)s$/', 'ma\1'], + ['/^Mes(dame|demoiselle)s$/', 'Ma\1'], + ['/^mes(sieur|seigneur)s$/', 'mon\1'], + ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], + + // Default rule + ['/s$/i', ''], + ]; + + /** + * A list of words which should not be inflected. + * This list is only used by singularize. + */ + private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sans|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; + + /** + * {@inheritdoc} + */ + public function singularize(string $plural): array + { + if ($this->isInflectedWord($plural)) { + return [$plural]; + } + + foreach (self::SINGULARIZE_REGEXP as $rule) { + [$regexp, $replace] = $rule; + + if (1 === preg_match($regexp, $plural)) { + return [preg_replace($regexp, $replace, $plural)]; + } + } + + return [$plural]; + } + + /** + * {@inheritdoc} + */ + public function pluralize(string $singular): array + { + if ($this->isInflectedWord($singular)) { + return [$singular]; + } + + foreach (self::PLURALIZE_REGEXP as $rule) { + [$regexp, $replace] = $rule; + + if (1 === preg_match($regexp, $singular)) { + return [preg_replace($regexp, $replace, $singular)]; + } + } + + return [$singular.'s']; + } + + private function isInflectedWord(string $word): bool + { + return 1 === preg_match(self::UNINFLECTED, $word); + } +} diff --git a/cacme/vendor/symfony/string/Inflector/InflectorInterface.php b/cacme/vendor/symfony/string/Inflector/InflectorInterface.php new file mode 100644 index 0000000..67f2834 --- /dev/null +++ b/cacme/vendor/symfony/string/Inflector/InflectorInterface.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 Symfony\Component\String\Inflector; + +interface InflectorInterface +{ + /** + * Returns the singular forms of a string. + * + * If the method can't determine the form with certainty, several possible singulars are returned. + * + * @return string[] + */ + public function singularize(string $plural): array; + + /** + * Returns the plural forms of a string. + * + * If the method can't determine the form with certainty, several possible plurals are returned. + * + * @return string[] + */ + public function pluralize(string $singular): array; +} diff --git a/cacme/vendor/symfony/string/LICENSE b/cacme/vendor/symfony/string/LICENSE new file mode 100644 index 0000000..5c7ba05 --- /dev/null +++ b/cacme/vendor/symfony/string/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019-2023 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/cacme/vendor/symfony/string/LazyString.php b/cacme/vendor/symfony/string/LazyString.php new file mode 100644 index 0000000..3733078 --- /dev/null +++ b/cacme/vendor/symfony/string/LazyString.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\String; + +/** + * A string whose value is computed lazily by a callback. + * + * @author Nicolas Grekas + */ +class LazyString implements \Stringable, \JsonSerializable +{ + private \Closure|string $value; + + /** + * @param callable|array $callback A callable or a [Closure, method] lazy-callable + */ + public static function fromCallable(callable|array $callback, mixed ...$arguments): static + { + if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '['.implode(', ', array_map('get_debug_type', $callback)).']')); + } + + $lazyString = new static(); + $lazyString->value = static function () use (&$callback, &$arguments, &$value): string { + if (null !== $arguments) { + if (!\is_callable($callback)) { + $callback[0] = $callback[0](); + $callback[1] = $callback[1] ?? '__invoke'; + } + $value = $callback(...$arguments); + $callback = self::getPrettyName($callback); + $arguments = null; + } + + return $value ?? ''; + }; + + return $lazyString; + } + + public static function fromStringable(string|int|float|bool|\Stringable $value): static + { + if (\is_object($value)) { + return static::fromCallable([$value, '__toString']); + } + + $lazyString = new static(); + $lazyString->value = (string) $value; + + return $lazyString; + } + + /** + * Tells whether the provided value can be cast to string. + */ + final public static function isStringable(mixed $value): bool + { + return \is_string($value) || $value instanceof \Stringable || \is_scalar($value); + } + + /** + * Casts scalars and stringable objects to strings. + * + * @throws \TypeError When the provided value is not stringable + */ + final public static function resolve(\Stringable|string|int|float|bool $value): string + { + return $value; + } + + public function __toString(): string + { + if (\is_string($this->value)) { + return $this->value; + } + + try { + return $this->value = ($this->value)(); + } catch (\Throwable $e) { + if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) { + $type = explode(', ', $e->getMessage()); + $type = substr(array_pop($type), 0, -\strlen(' returned')); + $r = new \ReflectionFunction($this->value); + $callback = $r->getStaticVariables()['callback']; + + $e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type)); + } + + throw $e; + } + } + + public function __sleep(): array + { + $this->__toString(); + + return ['value']; + } + + public function jsonSerialize(): string + { + return $this->__toString(); + } + + private function __construct() + { + } + + private static function getPrettyName(callable $callback): string + { + if (\is_string($callback)) { + return $callback; + } + + if (\is_array($callback)) { + $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0]; + $method = $callback[1]; + } elseif ($callback instanceof \Closure) { + $r = new \ReflectionFunction($callback); + + if (false !== strpos($r->name, '{closure}') || !$class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + return $r->name; + } + + $class = $class->name; + $method = $r->name; + } else { + $class = get_debug_type($callback); + $method = '__invoke'; + } + + return $class.'::'.$method; + } +} diff --git a/cacme/vendor/symfony/string/README.md b/cacme/vendor/symfony/string/README.md new file mode 100644 index 0000000..9c7e1e1 --- /dev/null +++ b/cacme/vendor/symfony/string/README.md @@ -0,0 +1,14 @@ +String Component +================ + +The String component provides an object-oriented API to strings and deals +with bytes, UTF-8 code points and grapheme clusters in a unified way. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/string.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/cacme/vendor/symfony/string/Resources/data/wcswidth_table_wide.php b/cacme/vendor/symfony/string/Resources/data/wcswidth_table_wide.php new file mode 100644 index 0000000..5a647e6 --- /dev/null +++ b/cacme/vendor/symfony/string/Resources/data/wcswidth_table_wide.php @@ -0,0 +1,1143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +if (!\function_exists(u::class)) { + function u(?string $string = ''): UnicodeString + { + return new UnicodeString($string ?? ''); + } +} + +if (!\function_exists(b::class)) { + function b(?string $string = ''): ByteString + { + return new ByteString($string ?? ''); + } +} + +if (!\function_exists(s::class)) { + /** + * @return UnicodeString|ByteString + */ + function s(?string $string = ''): AbstractString + { + $string = $string ?? ''; + + return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); + } +} diff --git a/cacme/vendor/symfony/string/Slugger/AsciiSlugger.php b/cacme/vendor/symfony/string/Slugger/AsciiSlugger.php new file mode 100644 index 0000000..548a6b9 --- /dev/null +++ b/cacme/vendor/symfony/string/Slugger/AsciiSlugger.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 Symfony\Component\String\Slugger; + +use Symfony\Component\String\AbstractUnicodeString; +use Symfony\Component\String\UnicodeString; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +if (!interface_exists(LocaleAwareInterface::class)) { + throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".'); +} + +/** + * @author Titouan Galopin + */ +class AsciiSlugger implements SluggerInterface, LocaleAwareInterface +{ + private const LOCALE_TO_TRANSLITERATOR_ID = [ + 'am' => 'Amharic-Latin', + 'ar' => 'Arabic-Latin', + 'az' => 'Azerbaijani-Latin', + 'be' => 'Belarusian-Latin', + 'bg' => 'Bulgarian-Latin', + 'bn' => 'Bengali-Latin', + 'de' => 'de-ASCII', + 'el' => 'Greek-Latin', + 'fa' => 'Persian-Latin', + 'he' => 'Hebrew-Latin', + 'hy' => 'Armenian-Latin', + 'ka' => 'Georgian-Latin', + 'kk' => 'Kazakh-Latin', + 'ky' => 'Kirghiz-Latin', + 'ko' => 'Korean-Latin', + 'mk' => 'Macedonian-Latin', + 'mn' => 'Mongolian-Latin', + 'or' => 'Oriya-Latin', + 'ps' => 'Pashto-Latin', + 'ru' => 'Russian-Latin', + 'sr' => 'Serbian-Latin', + 'sr_Cyrl' => 'Serbian-Latin', + 'th' => 'Thai-Latin', + 'tk' => 'Turkmen-Latin', + 'uk' => 'Ukrainian-Latin', + 'uz' => 'Uzbek-Latin', + 'zh' => 'Han-Latin', + ]; + + private ?string $defaultLocale; + private \Closure|array $symbolsMap = [ + 'en' => ['@' => 'at', '&' => 'and'], + ]; + + /** + * Cache of transliterators per locale. + * + * @var \Transliterator[] + */ + private array $transliterators = []; + + public function __construct(string $defaultLocale = null, array|\Closure $symbolsMap = null) + { + $this->defaultLocale = $defaultLocale; + $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; + } + + /** + * {@inheritdoc} + */ + public function setLocale(string $locale) + { + $this->defaultLocale = $locale; + } + + /** + * {@inheritdoc} + */ + public function getLocale(): string + { + return $this->defaultLocale; + } + + /** + * {@inheritdoc} + */ + public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString + { + $locale = $locale ?? $this->defaultLocale; + + $transliterator = []; + if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) { + // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl) + $transliterator = ['de-ASCII']; + } elseif (\function_exists('transliterator_transliterate') && $locale) { + $transliterator = (array) $this->createTransliterator($locale); + } + + if ($this->symbolsMap instanceof \Closure) { + // If the symbols map is passed as a closure, there is no need to fallback to the parent locale + // as the closure can just provide substitutions for all locales of interest. + $symbolsMap = $this->symbolsMap; + array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) { + return $symbolsMap($s, $locale); + }); + } + + $unicodeString = (new UnicodeString($string))->ascii($transliterator); + + if (\is_array($this->symbolsMap)) { + $map = null; + if (isset($this->symbolsMap[$locale])) { + $map = $this->symbolsMap[$locale]; + } else { + $parent = self::getParentLocale($locale); + if ($parent && isset($this->symbolsMap[$parent])) { + $map = $this->symbolsMap[$parent]; + } + } + if ($map) { + foreach ($map as $char => $replace) { + $unicodeString = $unicodeString->replace($char, ' '.$replace.' '); + } + } + } + + return $unicodeString + ->replaceMatches('/[^A-Za-z0-9]++/', $separator) + ->trim($separator) + ; + } + + private function createTransliterator(string $locale): ?\Transliterator + { + if (\array_key_exists($locale, $this->transliterators)) { + return $this->transliterators[$locale]; + } + + // Exact locale supported, cache and return + if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) { + return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); + } + + // Locale not supported and no parent, fallback to any-latin + if (!$parent = self::getParentLocale($locale)) { + return $this->transliterators[$locale] = null; + } + + // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales + if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) { + $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); + } + + return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; + } + + private static function getParentLocale(?string $locale): ?string + { + if (!$locale) { + return null; + } + if (false === $str = strrchr($locale, '_')) { + // no parent locale + return null; + } + + return substr($locale, 0, -\strlen($str)); + } +} diff --git a/cacme/vendor/symfony/string/Slugger/SluggerInterface.php b/cacme/vendor/symfony/string/Slugger/SluggerInterface.php new file mode 100644 index 0000000..c679ed9 --- /dev/null +++ b/cacme/vendor/symfony/string/Slugger/SluggerInterface.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\String\Slugger; + +use Symfony\Component\String\AbstractUnicodeString; + +/** + * Creates a URL-friendly slug from a given string. + * + * @author Titouan Galopin + */ +interface SluggerInterface +{ + /** + * Creates a slug for the given string and locale, using appropriate transliteration when needed. + */ + public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString; +} diff --git a/cacme/vendor/symfony/string/UnicodeString.php b/cacme/vendor/symfony/string/UnicodeString.php new file mode 100644 index 0000000..70cf4c5 --- /dev/null +++ b/cacme/vendor/symfony/string/UnicodeString.php @@ -0,0 +1,358 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; + +/** + * Represents a string of Unicode grapheme clusters encoded as UTF-8. + * + * A letter followed by combining characters (accents typically) form what Unicode defines + * as a grapheme cluster: a character as humans mean it in written texts. This class knows + * about the concept and won't split a letter apart from its combining accents. It also + * ensures all string comparisons happen on their canonically-composed representation, + * ignoring e.g. the order in which accents are listed when a letter has many of them. + * + * @see https://unicode.org/reports/tr15/ + * + * @author Nicolas Grekas + * @author Hugo Hamon + * + * @throws ExceptionInterface + */ +class UnicodeString extends AbstractUnicodeString +{ + public function __construct(string $string = '') + { + $this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string); + + if (false === $this->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + } + + public function append(string ...$suffix): static + { + $str = clone $this; + $str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix)); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + if (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function chunk(int $length = 1): array + { + if (1 > $length) { + throw new InvalidArgumentException('The chunk length must be greater than zero.'); + } + + if ('' === $this->string) { + return []; + } + + $rx = '/('; + while (65535 < $length) { + $rx .= '\X{65535}'; + $length -= 65535; + } + $rx .= '\X{'.$length.'})/u'; + + $str = clone $this; + $chunks = []; + + foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { + $str->string = $chunk; + $chunks[] = clone $str; + } + + return $chunks; + } + + public function endsWith(string|iterable|AbstractString $suffix): bool + { + if ($suffix instanceof AbstractString) { + $suffix = $suffix->string; + } elseif (!\is_string($suffix)) { + return parent::endsWith($suffix); + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form); + + if ('' === $suffix || false === $suffix) { + return false; + } + + if ($this->ignoreCase) { + return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8'); + } + + return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); + } + + public function equalsTo(string|iterable|AbstractString $string): bool + { + if ($string instanceof AbstractString) { + $string = $string->string; + } elseif (!\is_string($string)) { + return parent::equalsTo($string); + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form); + + if ('' !== $string && false !== $string && $this->ignoreCase) { + return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); + } + + return $string === $this->string; + } + + public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (!\is_string($needle)) { + return parent::indexOf($needle, $offset); + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); + + if ('' === $needle || false === $needle) { + return null; + } + + try { + $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset); + } catch (\ValueError $e) { + return null; + } + + return false === $i ? null : $i; + } + + public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (!\is_string($needle)) { + return parent::indexOfLast($needle, $offset); + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); + + if ('' === $needle || false === $needle) { + return null; + } + + $string = $this->string; + + if (0 > $offset) { + // workaround https://bugs.php.net/74264 + if (0 > $offset += grapheme_strlen($needle)) { + $string = grapheme_substr($string, 0, $offset); + } + $offset = 0; + } + + $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset); + + return false === $i ? null : $i; + } + + public function join(array $strings, string $lastGlue = null): static + { + $str = parent::join($strings, $lastGlue); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + return $str; + } + + public function length(): int + { + return grapheme_strlen($this->string); + } + + public function normalize(int $form = self::NFC): static + { + $str = clone $this; + + if (\in_array($form, [self::NFC, self::NFKC], true)) { + normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); + } elseif (!\in_array($form, [self::NFD, self::NFKD], true)) { + throw new InvalidArgumentException('Unsupported normalization form.'); + } elseif (!normalizer_is_normalized($str->string, $form)) { + $str->string = normalizer_normalize($str->string, $form); + $str->ignoreCase = null; + } + + return $str; + } + + public function prepend(string ...$prefix): static + { + $str = clone $this; + $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + if (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function replace(string $from, string $to): static + { + $str = clone $this; + normalizer_is_normalized($from) ?: $from = normalizer_normalize($from); + + if ('' !== $from && false !== $from) { + $tail = $str->string; + $result = ''; + $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; + + while ('' !== $tail && false !== $i = $indexOf($tail, $from)) { + $slice = grapheme_substr($tail, 0, $i); + $result .= $slice.$to; + $tail = substr($tail, \strlen($slice) + \strlen($from)); + } + + $str->string = $result.$tail; + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + if (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + } + + return $str; + } + + public function replaceMatches(string $fromRegexp, string|callable $to): static + { + $str = parent::replaceMatches($fromRegexp, $to); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + return $str; + } + + public function slice(int $start = 0, int $length = null): static + { + $str = clone $this; + + $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647); + + return $str; + } + + public function splice(string $replacement, int $start = 0, int $length = null): static + { + $str = clone $this; + + $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0; + $length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length; + $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + if (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (1 > $limit = $limit ?? 2147483647) { + throw new InvalidArgumentException('Split limit must be a positive integer.'); + } + + if ('' === $delimiter) { + throw new InvalidArgumentException('Split delimiter is empty.'); + } + + if (null !== $flags) { + return parent::split($delimiter.'u', $limit, $flags); + } + + normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter); + + if (false === $delimiter) { + throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); + } + + $str = clone $this; + $tail = $this->string; + $chunks = []; + $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; + + while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) { + $str->string = grapheme_substr($tail, 0, $i); + $chunks[] = clone $str; + $tail = substr($tail, \strlen($str->string) + \strlen($delimiter)); + --$limit; + } + + $str->string = $tail; + $chunks[] = clone $str; + + return $chunks; + } + + public function startsWith(string|iterable|AbstractString $prefix): bool + { + if ($prefix instanceof AbstractString) { + $prefix = $prefix->string; + } elseif (!\is_string($prefix)) { + return parent::startsWith($prefix); + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form); + + if ('' === $prefix || false === $prefix) { + return false; + } + + if ($this->ignoreCase) { + return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8'); + } + + return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); + } + + public function __wakeup() + { + if (!\is_string($this->string)) { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); + } + + public function __clone() + { + if (null === $this->ignoreCase) { + normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); + } + + $this->ignoreCase = false; + } +} diff --git a/cacme/vendor/symfony/string/composer.json b/cacme/vendor/symfony/string/composer.json new file mode 100644 index 0000000..187323f --- /dev/null +++ b/cacme/vendor/symfony/string/composer.json @@ -0,0 +1,42 @@ +{ + "name": "symfony/string", + "type": "library", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "keywords": ["string", "utf8", "utf-8", "grapheme", "i18n", "unicode"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.0.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\String\\": "" }, + "files": [ "Resources/functions.php" ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/cacme/vendor/webman/console/.gitignore b/cacme/vendor/webman/console/.gitignore new file mode 100644 index 0000000..67c6bbb --- /dev/null +++ b/cacme/vendor/webman/console/.gitignore @@ -0,0 +1,6 @@ +build +vendor +.idea +.vscode +.phpunit* +composer.lock \ No newline at end of file diff --git a/cacme/vendor/webman/console/README.md b/cacme/vendor/webman/console/README.md new file mode 100644 index 0000000..3d7e6ee --- /dev/null +++ b/cacme/vendor/webman/console/README.md @@ -0,0 +1,3 @@ +# console +webman console +https://www.workerman.net/plugin/1 diff --git a/cacme/vendor/webman/console/composer.json b/cacme/vendor/webman/console/composer.json new file mode 100644 index 0000000..446665b --- /dev/null +++ b/cacme/vendor/webman/console/composer.json @@ -0,0 +1,37 @@ +{ + "name": "webman/console", + "type": "library", + "keywords": [ + "webman console" + ], + "homepage": "http://www.workerman.net", + "license": "MIT", + "description": "Webman console", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/webman-php/console/issues", + "forum": "http://www.workerman.net/questions", + "wiki": "http://www.workerman.net/doc/webman", + "source": "https://github.com/webman-php/console" + }, + "require": { + "symfony/console": ">=5.0", + "doctrine/inflector": "^2.0" + }, + "autoload": { + "psr-4": { + "Webman\\Console\\" : "src" + } + }, + "require-dev": { + "workerman/webman": "^1.0" + } +} diff --git a/cacme/vendor/webman/console/src/Application.php b/cacme/vendor/webman/console/src/Application.php new file mode 100644 index 0000000..d527bc8 --- /dev/null +++ b/cacme/vendor/webman/console/src/Application.php @@ -0,0 +1,115 @@ +load(); + } else { + Dotenv::createMutable(base_path())->load(); + } + } + + Config::reload(config_path(), ['route', 'container']); + + Worker::$onMasterReload = function (){ + if (function_exists('opcache_get_status')) { + if ($status = opcache_get_status()) { + if (isset($status['scripts']) && $scripts = $status['scripts']) { + foreach (array_keys($scripts) as $file) { + opcache_invalidate($file, true); + } + } + } + } + }; + + $config = config('server'); + Worker::$pidFile = $config['pid_file']; + Worker::$stdoutFile = $config['stdout_file']; + Worker::$logFile = $config['log_file']; + Worker::$eventLoopClass = $config['event_loop'] ?? ''; + TcpConnection::$defaultMaxPackageSize = $config['max_package_size'] ?? 10*1024*1024; + if (property_exists(Worker::class, 'statusFile')) { + Worker::$statusFile = $config['status_file'] ?? ''; + } + if (property_exists(Worker::class, 'stopTimeout')) { + Worker::$stopTimeout = $config['stop_timeout'] ?? 2; + } + + if ($config['listen']) { + $worker = new Worker($config['listen'], $config['context']); + $property_map = [ + 'name', + 'count', + 'user', + 'group', + 'reusePort', + 'transport', + 'protocol' + ]; + foreach ($property_map as $property) { + if (isset($config[$property])) { + $worker->$property = $config[$property]; + } + } + + $worker->onWorkerStart = function ($worker) { + require_once base_path() . '/support/bootstrap.php'; + $app = new App($worker, Container::instance(), Log::channel('default'), app_path(), public_path()); + Http::requestClass(config('app.request_class', config('server.request_class', Request::class))); + $worker->onMessage = [$app, 'onMessage']; + }; + } + + // Windows does not support custom processes. + if (\DIRECTORY_SEPARATOR === '/') { + foreach (config('process', []) as $process_name => $config) { + // Remove monitor process. + if (class_exists(\Phar::class, false) && \Phar::running() && 'monitor' === $process_name) { + continue; + } + worker_start($process_name, $config); + } + foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + foreach ($project['process'] ?? [] as $process_name => $config) { + worker_start("plugin.$firm.$name.$process_name", $config); + } + } + } + } + Worker::runAll(); + } +} diff --git a/cacme/vendor/webman/console/src/Command.php b/cacme/vendor/webman/console/src/Command.php new file mode 100644 index 0000000..ac87d6f --- /dev/null +++ b/cacme/vendor/webman/console/src/Command.php @@ -0,0 +1,54 @@ +installCommands(__DIR__ . '/Commands', 'Webman\Console\Commands'); + } + + public function installCommands($path, $namspace = 'app\command') + { + $dir_iterator = new \RecursiveDirectoryIterator($path); + $iterator = new \RecursiveIteratorIterator($dir_iterator); + foreach ($iterator as $file) { + /** @var \SplFileInfo $file */ + if (strpos($file->getFilename(), '.') === 0) { + continue; + } + if ($file->getExtension() !== 'php') { + continue; + } + // abc\def.php + $relativePath = str_replace(str_replace('/', '\\', $path . '\\'), '', str_replace('/', '\\', $file->getRealPath())); + // app\command\abc + $realNamespace = trim($namspace . '\\' . trim(dirname(str_replace('\\', DIRECTORY_SEPARATOR, $relativePath)), '.'), '\\'); + $realNamespace = str_replace('/', '\\', $realNamespace); + // app\command\doc\def + $class_name = trim($realNamespace . '\\' . $file->getBasename('.php'), '\\'); + if (!class_exists($class_name) || !is_a($class_name, Commands::class, true)) { + continue; + } + $reflection = new \ReflectionClass($class_name); + if ($reflection->isAbstract()) { + continue; + } + $properties = $reflection->getStaticProperties(); + $name = $properties['defaultName']; + if (!$name) { + throw new RuntimeException("Command {$class_name} has no defaultName"); + } + $description = $properties['defaultDescription'] ?? ''; + $command = Container::get($class_name); + $command->setName($name)->setDescription($description); + $this->add($command); + } + } +} diff --git a/cacme/vendor/webman/console/src/Commands/AppPluginCreateCommand.php b/cacme/vendor/webman/console/src/Commands/AppPluginCreateCommand.php new file mode 100644 index 0000000..ca3f186 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/AppPluginCreateCommand.php @@ -0,0 +1,472 @@ +addArgument('name', InputArgument::REQUIRED, 'App plugin name'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Create App Plugin $name"); + + if (strpos($name, '/') !== false) { + $output->writeln('Bad name, name must not contain character \'/\''); + return self::FAILURE; + } + + // Create dir config/plugin/$name + if (is_dir($plugin_config_path = base_path()."/plugin/$name")) { + $output->writeln("Dir $plugin_config_path already exists"); + return self::FAILURE; + } + + $this->createAll($name); + + return self::SUCCESS; + } + + /** + * @param $name + * @return void + */ + protected function createAll($name) + { + $base_path = base_path(); + $this->mkdir("$base_path/plugin/$name/app/controller", 0777, true); + $this->mkdir("$base_path/plugin/$name/app/model", 0777, true); + $this->mkdir("$base_path/plugin/$name/app/middleware", 0777, true); + $this->mkdir("$base_path/plugin/$name/app/view/index", 0777, true); + $this->mkdir("$base_path/plugin/$name/config", 0777, true); + $this->mkdir("$base_path/plugin/$name/public", 0777, true); + $this->mkdir("$base_path/plugin/$name/api", 0777, true); + $this->createFunctionsFile("$base_path/plugin/$name/app/functions.php"); + $this->createControllerFile("$base_path/plugin/$name/app/controller/IndexController.php", $name); + $this->createViewFile("$base_path/plugin/$name/app/view/index/index.html"); + $this->createConfigFiles("$base_path/plugin/$name/config", $name); + $this->createApiFiles("$base_path/plugin/$name/api", $name); + } + + /** + * @param $path + * @return void + */ + protected function mkdir($path) + { + if (is_dir($path)) { + return; + } + echo "Create $path\r\n"; + mkdir($path, 0777, true); + } + + /** + * @param $path + * @param $name + * @return void + */ + protected function createControllerFile($path, $name) + { + $content = << '$name']); + } + +} + +EOF; + file_put_contents($path, $content); + + } + + /** + * @param $path + * @return void + */ + protected function createViewFile($path) + { + $content = << + + + + + + + webman app plugin + + + +hello + + + + +EOF; + file_put_contents($path, $content); + + } + + + /** + * @param $file + * @return void + */ + protected function createFunctionsFile($file) + { + $content = << static::getMenus()]; + } + + /** + * 获取菜单 + * + * @return array|mixed + */ + public static function getMenus() + { + clearstatcache(); + if (is_file(\$menu_file = __DIR__ . '/../config/menu.php')) { + \$menus = include \$menu_file; + return \$menus ?: []; + } + return []; + } + + /** + * 删除不需要的菜单 + * + * @param \$previous_menus + * @return void + */ + public static function removeUnnecessaryMenus(\$previous_menus) + { + \$menus_to_remove = array_diff(Menu::column(\$previous_menus, 'name'), Menu::column(static::getMenus(), 'name')); + foreach (\$menus_to_remove as \$name) { + Menu::delete(\$name); + } + } + +} +EOF; + + file_put_contents("$base/Install.php", $content); + + } + + /** + * @param $base + * @param $name + * @return void + */ + protected function createConfigFiles($base, $name) + { + // app.php + $content = << true, + 'controller_suffix' => 'Controller', + 'controller_reuse' => false, + 'version' => '1.0.0' +]; + +EOF; + file_put_contents("$base/app.php", $content); + + // menu.php + $content = << [ + base_path() . '/plugin/$name/app/functions.php', + ] +]; +EOF; + file_put_contents("$base/autoload.php", $content); + + // container.php + $content = << support\\exception\\Handler::class, +]; + +EOF; + file_put_contents("$base/exception.php", $content); + + // log.php + $content = << [ + 'handlers' => [ + [ + 'class' => Monolog\\Handler\\RotatingFileHandler::class, + 'constructor' => [ + runtime_path() . '/logs/$name.log', + 7, + Monolog\\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\\Formatter\\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ] + ], + ], +]; + +EOF; + file_put_contents("$base/log.php", $content); + + // middleware.php + $content = << [ + + ] +]; + +EOF; + file_put_contents("$base/middleware.php", $content); + + // process.php + $content = << [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'database' => 0, + ], +]; + +EOF; + file_put_contents("$base/redis.php", $content); + + // route.php + $content = << true, + 'middleware' => [], // Static file Middleware +]; + +EOF; + file_put_contents("$base/static.php", $content); + + // translation.php + $content = << 'zh_CN', + // Fallback language + 'fallback_locale' => ['zh_CN', 'en'], + // Folder where language files are stored + 'path' => base_path() . "/plugin/$name/resource/translations", +]; + +EOF; + file_put_contents("$base/translation.php", $content); + + // view.php + $content = << Raw::class +]; + +EOF; + file_put_contents("$base/view.php", $content); + + // thinkorm.php + $content = <<setName(static::$defaultName)->setDescription(static::$defaultDescription); + $this->addArgument('name', InputArgument::REQUIRED, 'App plugin name'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Install App Plugin $name"); + $class = "\\plugin\\$name\\api\\Install"; + if (!method_exists($class, 'install')) { + throw new \RuntimeException("Method $class::install not exists"); + } + call_user_func([$class, 'install'], config("plugin.$name.app.version")); + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/AppPluginUninstallCommand.php b/cacme/vendor/webman/console/src/Commands/AppPluginUninstallCommand.php new file mode 100644 index 0000000..62dad9e --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/AppPluginUninstallCommand.php @@ -0,0 +1,42 @@ +addArgument('name', InputArgument::REQUIRED, 'App plugin name'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Uninstall App Plugin $name"); + $class = "\\plugin\\$name\\api\\Install"; + if (!method_exists($class, 'uninstall')) { + throw new \RuntimeException("Method $class::uninstall not exists"); + } + call_user_func([$class, 'uninstall'], config("plugin.$name.app.version")); + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/BuildBinCommand.php b/cacme/vendor/webman/console/src/Commands/BuildBinCommand.php new file mode 100644 index 0000000..8dcc1b5 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/BuildBinCommand.php @@ -0,0 +1,149 @@ +addArgument('version', InputArgument::OPTIONAL, 'PHP version'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->checkEnv(); + + $output->writeln('Phar packing...'); + + $version = $input->getArgument('version'); + if (!$version) { + $version = (float)PHP_VERSION; + } + $version = $version >= 8.0 ? $version : 8.1; + $supportZip = class_exists(ZipArchive::class); + $microZipFileName = $supportZip ? "php$version.micro.sfx.zip" : "php$version.micro.sfx"; + $pharFileName = config('plugin.webman.console.app.phar_filename', 'webman.phar'); + $binFileName = config('plugin.webman.console.app.bin_filename', 'webman.bin'); + $this->buildDir = config('plugin.webman.console.app.build_dir', base_path() . '/build'); + $customIni = config('plugin.webman.console.app.custom_ini', ''); + + $binFile = "$this->buildDir/$binFileName"; + $pharFile = "$this->buildDir/$pharFileName"; + $zipFile = "$this->buildDir/$microZipFileName"; + $sfxFile = "$this->buildDir/php$version.micro.sfx"; + $customIniHeaderFile = "$this->buildDir/custominiheader.bin"; + + // 打包 + $command = new BuildPharCommand(); + $command->execute($input, $output); + + // 下载 micro.sfx.zip + if (!is_file($sfxFile) && !is_file($zipFile)) { + $domain = 'download.workerman.net'; + $output->writeln("\r\nDownloading PHP$version ..."); + if (extension_loaded('openssl')) { + $context = stream_context_create([ + 'ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + ] + ]); + $client = stream_socket_client("ssl://$domain:443", $context); + } else { + $client = stream_socket_client("tcp://$domain:80"); + } + + fwrite($client, "GET /php/$microZipFileName HTTP/1.0\r\nAccept: text/html\r\nHost: $domain\r\nUser-Agent: webman/console\r\n\r\n"); + $bodyLength = 0; + $bodyBuffer = ''; + $lastPercent = 0; + while (true) { + $buffer = fread($client, 65535); + if ($buffer !== false) { + $bodyBuffer .= $buffer; + if (!$bodyLength && $pos = strpos($bodyBuffer, "\r\n\r\n")) { + if (!preg_match('/Content-Length: (\d+)\r\n/', $bodyBuffer, $match)) { + $output->writeln("Download php$version.micro.sfx.zip failed"); + return self::FAILURE; + } + $firstLine = substr($bodyBuffer, 9, strpos($bodyBuffer, "\r\n") - 9); + if (!preg_match('/200 /', $bodyBuffer)) { + $output->writeln("Download php$version.micro.sfx.zip failed, $firstLine"); + return self::FAILURE; + } + $bodyLength = (int)$match[1]; + $bodyBuffer = substr($bodyBuffer, $pos + 4); + } + } + $receiveLength = strlen($bodyBuffer); + $percent = ceil($receiveLength * 100 / $bodyLength); + if ($percent != $lastPercent) { + echo '[' . str_pad('', $percent, '=') . '>' . str_pad('', 100 - $percent) . "$percent%]"; + echo $percent < 100 ? "\r" : "\n"; + } + $lastPercent = $percent; + if ($bodyLength && $receiveLength >= $bodyLength) { + file_put_contents($zipFile, $bodyBuffer); + break; + } + if ($buffer === false || !is_resource($client) || feof($client)) { + $output->writeln("Fail donwload PHP$version ..."); + return self::FAILURE; + } + } + } else { + $output->writeln("\r\nUse PHP$version ..."); + } + + // 解压 + if (!is_file($sfxFile) && $supportZip) { + $zip = new ZipArchive; + $zip->open($zipFile, ZipArchive::CHECKCONS); + $zip->extractTo($this->buildDir); + } + + // 生成二进制文件 + file_put_contents($binFile, file_get_contents($sfxFile)); + // 自定义INI + if (!empty($customIni)) { + if (file_exists($customIniHeaderFile)) { + unlink($customIniHeaderFile); + } + $f = fopen($customIniHeaderFile, 'wb'); + fwrite($f, "\xfd\xf6\x69\xe6"); + fwrite($f, pack('N', strlen($customIni))); + fwrite($f, $customIni); + fclose($f); + file_put_contents($binFile, file_get_contents($customIniHeaderFile),FILE_APPEND); + unlink($customIniHeaderFile); + } + file_put_contents($binFile, file_get_contents($pharFile), FILE_APPEND); + + // 添加执行权限 + chmod($binFile, 0755); + + $output->writeln("\r\nSaved $binFileName to $binFile\r\nBuild Success!\r\n"); + + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/BuildPharCommand.php b/cacme/vendor/webman/console/src/Commands/BuildPharCommand.php new file mode 100644 index 0000000..43985ed --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/BuildPharCommand.php @@ -0,0 +1,148 @@ +buildDir = config('plugin.webman.console.app.build_dir', base_path() . '/build'); + } + + /** + * @return void + * @deprecated 暂时保留 phar:pack 命令,下一个版本再取消 + */ + protected function configure() + { + $this->setAliases([ + 'phar:pack', + ]); + parent::configure(); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->checkEnv(); + if (!file_exists($this->buildDir) && !is_dir($this->buildDir)) { + if (!mkdir($this->buildDir,0777,true)) { + throw new RuntimeException("Failed to create phar file output directory. Please check the permission."); + } + } + + $phar_filename = config('plugin.webman.console.app.phar_filename', 'webman.phar'); + if (empty($phar_filename)) { + throw new RuntimeException('Please set the phar filename.'); + } + + $phar_file = rtrim($this->buildDir,DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $phar_filename; + if (file_exists($phar_file)) { + unlink($phar_file); + } + + $exclude_pattern = config('plugin.webman.console.app.exclude_pattern',''); + + $phar = new Phar($phar_file,0,'webman'); + + $phar->startBuffering(); + + $signature_algorithm = config('plugin.webman.console.app.signature_algorithm'); + if (!in_array($signature_algorithm,[Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512,Phar::OPENSSL])) { + throw new RuntimeException('The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.'); + } + if ($signature_algorithm === Phar::OPENSSL) { + $private_key_file = config('plugin.webman.console.app.private_key_file'); + if (!file_exists($private_key_file)) { + throw new RuntimeException("If the value of the signature algorithm is 'Phar::OPENSSL', you must set the private key file."); + } + $private = openssl_get_privatekey(file_get_contents($private_key_file)); + $pkey = ''; + openssl_pkey_export($private, $pkey); + $phar->setSignatureAlgorithm($signature_algorithm, $pkey); + } else { + $phar->setSignatureAlgorithm($signature_algorithm); + } + + $phar->buildFromDirectory(BASE_PATH,$exclude_pattern); + + + $exclude_files = config('plugin.webman.console.app.exclude_files',[]); + // 打包生成的phar和bin文件是面向生产环境的,所以以下这些命令没有任何意义,执行的话甚至会出错,需要排除在外。 + $exclude_command_files = [ + 'AppPluginCreateCommand.php', + 'BuildBinCommand.php', + 'BuildPharCommand.php', + 'MakeBootstrapCommand.php', + 'MakeCommandCommand.php', + 'MakeControllerCommand.php', + 'MakeMiddlewareCommand.php', + 'MakeModelCommand.php', + 'PluginCreateCommand.php', + 'PluginDisableCommand.php', + 'PluginEnableCommand.php', + 'PluginExportCommand.php', + 'PluginInstallCommand.php', + 'PluginUninstallCommand.php' + ]; + $exclude_command_files = array_map(function ($cmd_file) { + return 'vendor/webman/console/src/Commands/'.$cmd_file; + },$exclude_command_files); + $exclude_files = array_unique(array_merge($exclude_command_files,$exclude_files)); + foreach ($exclude_files as $file) { + if($phar->offsetExists($file)){ + $phar->delete($file); + } + } + + $output->writeln('Files collect complete, begin add file to Phar.'); + + $phar->setStub("#!/usr/bin/env php +writeln('Write requests to the Phar archive, save changes to disk.'); + + $phar->stopBuffering(); + unset($phar); + return self::SUCCESS; + } + + /** + * @throws RuntimeException + */ + public function checkEnv(): void + { + if (!class_exists(Phar::class, false)) { + throw new RuntimeException("The 'phar' extension is required for build phar package"); + } + + if (ini_get('phar.readonly')) { + $command = static::$defaultName; + throw new RuntimeException( + "The 'phar.readonly' is 'On', build phar must setting it 'Off' or exec with 'php -d phar.readonly=0 ./webman $command'" + ); + } + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/ConnectionsCommand.php b/cacme/vendor/webman/console/src/Commands/ConnectionsCommand.php new file mode 100644 index 0000000..2244a54 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/ConnectionsCommand.php @@ -0,0 +1,29 @@ +writeln('Can not find php.ini'); + return self::FAILURE; + } + $output->writeln("Location $php_ini_file"); + $disable_functions_str = ini_get("disable_functions"); + if (!$disable_functions_str) { + $output->writeln('Ok'); + } + + $functions_required = [ + "stream_socket_server", + "stream_socket_accept", + "stream_socket_client", + "pcntl_signal_dispatch", + "pcntl_signal", + "pcntl_alarm", + "pcntl_fork", + "posix_getuid", + "posix_getpwuid", + "posix_kill", + "posix_setsid", + "posix_getpid", + "posix_getpwnam", + "posix_getgrnam", + "posix_getgid", + "posix_setgid", + "posix_initgroups", + "posix_setuid", + "posix_isatty", + "proc_open", + "proc_get_status", + "proc_close", + "shell_exec", + "exec", + ]; + + $has_disbaled_functions = false; + foreach ($functions_required as $func) { + if (strpos($disable_functions_str, $func) !== false) { + $has_disbaled_functions = true; + break; + } + } + + $disable_functions = explode(",", $disable_functions_str); + $disable_functions_removed = []; + foreach ($disable_functions as $index => $func) { + $func = trim($func); + foreach ($functions_required as $func_prefix) { + if (strpos($func, $func_prefix) === 0) { + $disable_functions_removed[$func] = $func; + unset($disable_functions[$index]); + } + } + } + + $php_ini_content = file_get_contents($php_ini_file); + if (!$php_ini_content) { + $output->writeln("$php_ini_file content empty"); + return self::FAILURE; + } + + $new_disable_functions_str = implode(",", $disable_functions); + $php_ini_content = preg_replace("/\ndisable_functions *?=[^\n]+/", "\ndisable_functions = $new_disable_functions_str", $php_ini_content); + + file_put_contents($php_ini_file, $php_ini_content); + + foreach ($disable_functions_removed as $func) { + $output->write(str_pad($func, 30)); + $output->writeln('enabled'); + } + + $output->writeln('Succes'); + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/InstallCommand.php b/cacme/vendor/webman/console/src/Commands/InstallCommand.php new file mode 100644 index 0000000..2f1de64 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/InstallCommand.php @@ -0,0 +1,40 @@ +writeln("Execute installation for webman"); + $install_function = "\\Webman\\Install::install"; + if (is_callable($install_function)) { + $install_function(); + return self::SUCCESS; + } + $output->writeln('This command requires webman-framework version >= 1.3.0'); + return self::FAILURE; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/MakeBootstrapCommand.php b/cacme/vendor/webman/console/src/Commands/MakeBootstrapCommand.php new file mode 100644 index 0000000..e41ced9 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/MakeBootstrapCommand.php @@ -0,0 +1,117 @@ +addArgument('name', InputArgument::REQUIRED, 'Bootstrap name'); + $this->addArgument('enable', InputArgument::OPTIONAL, 'Enable or not'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $enable = in_array($input->getArgument('enable'), ['no', '0', 'false', 'n']) ? false : true; + $output->writeln("Make bootstrap $name"); + + $name = str_replace('\\', '/', $name); + if (!$bootstrap_str = Util::guessPath(app_path(), 'bootstrap')) { + $bootstrap_str = Util::guessPath(app_path(), 'controller') === 'Controller' ? 'Bootstrap' : 'bootstrap'; + } + $upper = $bootstrap_str === 'Bootstrap'; + if (!($pos = strrpos($name, '/'))) { + $name = ucfirst($name); + $file = app_path() . "/$bootstrap_str/$name.php"; + $namespace = $upper ? 'App\Bootstrap' : 'app\bootstrap'; + } else { + if($real_name = Util::guessPath(app_path(), $name)) { + $name = $real_name; + } + if ($upper && !$real_name) { + $name = preg_replace_callback('/\/([a-z])/', function ($matches) { + return '/' . strtoupper($matches[1]); + }, ucfirst($name)); + } + $path = "$bootstrap_str/" . substr($upper ? ucfirst($name) : $name, 0, $pos); + $name = ucfirst(substr($name, $pos + 1)); + $file = app_path() . "/$path/$name.php"; + $namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path); + } + + $this->createBootstrap($name, $namespace, $file); + if ($enable) { + $this->addConfig("$namespace\\$name", config_path() . '/bootstrap.php'); + } + + return self::SUCCESS; + } + + /** + * @param $name + * @param $namespace + * @param $file + * @return void + */ + protected function createBootstrap($name, $namespace, $file) + { + $path = pathinfo($file, PATHINFO_DIRNAME); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + $bootstrap_content = <<addArgument('name', InputArgument::REQUIRED, 'Command name'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $command = $name = trim($input->getArgument('name')); + $output->writeln("Make command $name"); + + // make:command 不支持子目录 + $name = str_replace(['\\', '/'], '', $name); + if (!$command_str = Util::guessPath(app_path(), 'command')) { + $command_str = Util::guessPath(app_path(), 'controller') === 'Controller' ? 'Command' : 'command'; + } + $items= explode(':', $name); + $name=''; + foreach ($items as $item) { + $name.=ucfirst($item); + } + $file = app_path() . "/$command_str/$name.php"; + $upper = $command_str === 'Command'; + $namespace = $upper ? 'App\Command' : 'app\command'; + $this->createCommand($name, $namespace, $file, $command); + + return self::SUCCESS; + } + + protected function getClassName($name) + { + return preg_replace_callback('/:([a-zA-Z])/', function ($matches) { + return strtoupper($matches[1]); + }, ucfirst($name)) . 'Command'; + } + + /** + * @param $name + * @param $namespace + * @param $path + * @return void + */ + protected function createCommand($name, $namespace, $file, $command) + { + $path = pathinfo($file, PATHINFO_DIRNAME); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + $desc = str_replace(':', ' ', $command); + $command_content = <<addArgument('name', InputArgument::OPTIONAL, 'Name description'); + } + + /** + * @param InputInterface \$input + * @param OutputInterface \$output + * @return int + */ + protected function execute(InputInterface \$input, OutputInterface \$output): int + { + \$name = \$input->getArgument('name'); + \$output->writeln('Hello $command'); + return self::SUCCESS; + } + +} + +EOF; + file_put_contents($file, $command_content); + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/MakeControllerCommand.php b/cacme/vendor/webman/console/src/Commands/MakeControllerCommand.php new file mode 100644 index 0000000..3c78581 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/MakeControllerCommand.php @@ -0,0 +1,103 @@ +addArgument('name', InputArgument::REQUIRED, 'Controller name'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Make controller $name"); + $suffix = config('app.controller_suffix', ''); + + if ($suffix && !strpos($name, $suffix)) { + $name .= $suffix; + } + + $name = str_replace('\\', '/', $name); + if (!($pos = strrpos($name, '/'))) { + $name = ucfirst($name); + $controller_str = Util::guessPath(app_path(), 'controller') ?: 'controller'; + $file = app_path() . "/$controller_str/$name.php"; + $namespace = $controller_str === 'Controller' ? 'App\Controller' : 'app\controller'; + } else { + $name_str = substr($name, 0, $pos); + if($real_name_str = Util::guessPath(app_path(), $name_str)) { + $name_str = $real_name_str; + } else if ($real_section_name = Util::guessPath(app_path(), strstr($name_str, '/', true))) { + $upper = strtolower($real_section_name[0]) !== $real_section_name[0]; + } else if ($real_base_controller = Util::guessPath(app_path(), 'controller')) { + $upper = strtolower($real_base_controller[0]) !== $real_base_controller[0]; + } + $upper = $upper ?? strtolower($name_str[0]) !== $name_str[0]; + if ($upper && !$real_name_str) { + $name_str = preg_replace_callback('/\/([a-z])/', function ($matches) { + return '/' . strtoupper($matches[1]); + }, ucfirst($name_str)); + } + $path = "$name_str/" . ($upper ? 'Controller' : 'controller'); + $name = ucfirst(substr($name, $pos + 1)); + $file = app_path() . "/$path/$name.php"; + $namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path); + } + $this->createController($name, $namespace, $file); + + return self::SUCCESS; + } + + /** + * @param $name + * @param $namespace + * @param $file + * @return void + */ + protected function createController($name, $namespace, $file) + { + $path = pathinfo($file, PATHINFO_DIRNAME); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + $controller_content = <<addArgument('name', InputArgument::REQUIRED, 'Middleware name'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Make middleware $name"); + + $name = str_replace('\\', '/', $name); + if (!$middleware_str = Util::guessPath(app_path(), 'middleware')) { + $middleware_str = Util::guessPath(app_path(), 'controller') === 'Controller' ? 'Middleware' : 'middleware'; + } + $upper = $middleware_str === 'Middleware'; + if (!($pos = strrpos($name, '/'))) { + $name = ucfirst($name); + $file = app_path() . "/$middleware_str/$name.php"; + $namespace = $upper ? 'App\Middleware' : 'app\middleware'; + } else { + if($real_name = Util::guessPath(app_path(), $name)) { + $name = $real_name; + } + if ($upper && !$real_name) { + $name = preg_replace_callback('/\/([a-z])/', function ($matches) { + return '/' . strtoupper($matches[1]); + }, ucfirst($name)); + } + $path = "$middleware_str/" . substr($upper ? ucfirst($name) : $name, 0, $pos); + $name = ucfirst(substr($name, $pos + 1)); + $file = app_path() . "/$path/$name.php"; + $namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path); + } + + $this->createMiddleware($name, $namespace, $file); + + return self::SUCCESS; + } + + + /** + * @param $name + * @param $namespace + * @param $path + * @return void + */ + protected function createMiddleware($name, $namespace, $file) + { + $path = pathinfo($file, PATHINFO_DIRNAME); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + $middleware_content = <<addArgument('name', InputArgument::REQUIRED, 'Model name'); + $this->addArgument('type', InputArgument::OPTIONAL, 'Type'); + $this->addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'Select database connection. '); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $name = Util::nameToClass($name); + $type = $input->getArgument('type'); + $connection = $input->getOption('connection'); + $output->writeln("Make model $name"); + if (!($pos = strrpos($name, '/'))) { + $name = ucfirst($name); + $model_str = Util::guessPath(app_path(), 'model') ?: 'model'; + $file = app_path() . "/$model_str/$name.php"; + $namespace = $model_str === 'Model' ? 'App\Model' : 'app\model'; + } else { + $name_str = substr($name, 0, $pos); + if($real_name_str = Util::guessPath(app_path(), $name_str)) { + $name_str = $real_name_str; + } else if ($real_section_name = Util::guessPath(app_path(), strstr($name_str, '/', true))) { + $upper = strtolower($real_section_name[0]) !== $real_section_name[0]; + } else if ($real_base_controller = Util::guessPath(app_path(), 'controller')) { + $upper = strtolower($real_base_controller[0]) !== $real_base_controller[0]; + } + $upper = $upper ?? strtolower($name_str[0]) !== $name_str[0]; + if ($upper && !$real_name_str) { + $name_str = preg_replace_callback('/\/([a-z])/', function ($matches) { + return '/' . strtoupper($matches[1]); + }, ucfirst($name_str)); + } + $path = "$name_str/" . ($upper ? 'Model' : 'model'); + $name = ucfirst(substr($name, $pos + 1)); + $file = app_path() . "/$path/$name.php"; + $namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path); + } + if (!$type) { + $database = config('database'); + if (isset($database['default']) && strpos($database['default'], 'plugin.') === 0) { + $database = false; + } + $thinkorm = config('thinkorm'); + if (isset($thinkorm['default']) && strpos($thinkorm['default'], 'plugin.') === 0) { + $thinkorm = false; + } + $type = !$database && $thinkorm ? 'tp' : 'laravel'; + } + if ($type == 'tp') { + $this->createTpModel($name, $namespace, $file, $connection); + } else { + $this->createModel($name, $namespace, $file, $connection); + } + + return self::SUCCESS; + } + + /** + * @param $class + * @param $namespace + * @param $file + * @param string|null $connection + * @return void + */ + protected function createModel($class, $namespace, $file, $connection = null) + { + $path = pathinfo($file, PATHINFO_DIRNAME); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + $table = Util::classToName($class); + $table_val = 'null'; + $pk = 'id'; + $properties = ''; + $connection = $connection ?: 'mysql'; + try { + $prefix = config("database.connections.$connection.prefix") ?? ''; + $database = config("database.connections.$connection.database"); + $inflector = InflectorFactory::create()->build(); + $table_plura = $inflector->pluralize($inflector->tableize($class)); + $con = Db::connection($connection); + if ($con->select("show tables like '{$prefix}{$table_plura}'")) { + $table_val = "'$table'"; + $table = "{$prefix}{$table_plura}"; + } else if ($con->select("show tables like '{$prefix}{$table}'")) { + $table_val = "'$table'"; + $table = "{$prefix}{$table}"; + } + $tableComment = $con->select('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]); + if (!empty($tableComment)) { + $comments = $tableComment[0]->table_comment ?? $tableComment[0]->TABLE_COMMENT; + $properties .= " * {$table} {$comments}" . PHP_EOL; + } + foreach ($con->select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) { + if ($item->COLUMN_KEY === 'PRI') { + $pk = $item->COLUMN_NAME; + $item->COLUMN_COMMENT .= "(主键)"; + } + $type = $this->getType($item->DATA_TYPE); + $properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n"; + } + } catch (\Throwable $e) { + echo $e->getMessage() . PHP_EOL; + } + $properties = rtrim($properties) ?: ' *'; + $model_content = <<query("show tables like '{$prefix}{$table}'")) { + $table = "{$prefix}{$table}"; + $table_val = "'$table'"; + } else if ($con->query("show tables like '{$prefix}{$table}s'")) { + $table = "{$prefix}{$table}s"; + $table_val = "'$table'"; + } + $tableComment = $con->query('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]); + if (!empty($tableComment)) { + $comments = $tableComment[0]['table_comment'] ?? $tableComment[0]['TABLE_COMMENT']; + $properties .= " * {$table} {$comments}" . PHP_EOL; + } + foreach ($con->query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) { + if ($item['COLUMN_KEY'] === 'PRI') { + $pk = $item['COLUMN_NAME']; + $item['COLUMN_COMMENT'] .= "(主键)"; + } + $type = $this->getType($item['DATA_TYPE']); + $properties .= " * @property $type \${$item['COLUMN_NAME']} {$item['COLUMN_COMMENT']}\n"; + } + } catch (\Throwable $e) { + echo $e->getMessage() . PHP_EOL; + } + $properties = rtrim($properties) ?: ' *'; + $model_content = <<addOption('name', 'name', InputOption::VALUE_REQUIRED, 'Plugin name, for example foo/my-admin'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = strtolower($input->getOption('name')); + $output->writeln("Create Plugin $name"); + if (!strpos($name, '/')) { + $output->writeln('Bad name, name must contain character \'/\' , for example foo/MyAdmin'); + return self::FAILURE; + } + + $namespace = Util::nameToNamespace($name); + + // Create dir config/plugin/$name + if (is_dir($plugin_config_path = config_path()."/plugin/$name")) { + $output->writeln("Dir $plugin_config_path already exists"); + return self::FAILURE; + } + + if (is_dir($plugin_path = base_path()."/vendor/$name")) { + $output->writeln("Dir $plugin_path already exists"); + return self::FAILURE; + } + + // Add psr-4 + if ($err = $this->addAutoloadToComposerJson($name, $namespace)) { + $output->writeln("$err"); + return self::FAILURE; + } + + $this->createConfigFiles($plugin_config_path); + + $this->createVendorFiles($name, $namespace, $plugin_path, $output); + + return self::SUCCESS; + } + + protected function addAutoloadToComposerJson($name, $namespace) + { + if (!is_file($composer_json_file = base_path()."/composer.json")) { + return "$composer_json_file not exists"; + } + $composer_json = json_decode($composer_json_str = file_get_contents($composer_json_file), true); + if (!$composer_json) { + return "Bad $composer_json_file"; + } + if(isset($composer_json['autoload']['psr-4'][$namespace."\\"])) { + return; + } + $namespace = str_replace("\\", "\\\\", $namespace); + $composer_json_str = str_replace('"psr-4": {', '"psr-4": {'."\n \"$namespace\\\\\" : \"vendor/$name/src\",", $composer_json_str); + file_put_contents($composer_json_file, $composer_json_str); + } + + protected function createConfigFiles($plugin_config_path) + { + mkdir($plugin_config_path, 0777, true); + $app_str = << true, +]; +EOF; + file_put_contents("$plugin_config_path/app.php", $app_str); + } + + protected function createVendorFiles($name, $namespace, $plugin_path, $output) + { + mkdir("$plugin_path/src", 0777, true); + $this->createComposerJson($name, $namespace, $plugin_path); + if (is_callable('exec')) { + exec("composer dumpautoload"); + } else { + $output->writeln("Please run command 'composer dumpautoload'"); + } + } + + /** + * @param $name + * @param $namespace + * @param $dest + * @return void + */ + protected function createComposerJson($name, $namespace, $dest) + { + $namespace = str_replace('\\', '\\\\', $namespace); + $composer_json_content = << \$dest) { + if (\$pos = strrpos(\$dest, '/')) { + \$parent_dir = base_path().'/'.substr(\$dest, 0, \$pos); + if (!is_dir(\$parent_dir)) { + mkdir(\$parent_dir, 0777, true); + } + } + //symlink(__DIR__ . "/\$source", base_path()."/\$dest"); + copy_dir(__DIR__ . "/\$source", base_path()."/\$dest"); + } + } + + /** + * uninstallByRelation + * @return void + */ + public static function uninstallByRelation() + { + foreach (static::\$pathRelation as \$source => \$dest) { + /*if (is_link(base_path()."/\$dest")) { + unlink(base_path()."/\$dest"); + }*/ + remove_dir(base_path()."/\$dest"); + } + } +} +EOT; + file_put_contents("$dest_dir/Install.php", $install_php_content); + } +} diff --git a/cacme/vendor/webman/console/src/Commands/PluginDisableCommand.php b/cacme/vendor/webman/console/src/Commands/PluginDisableCommand.php new file mode 100644 index 0000000..b02061e --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/PluginDisableCommand.php @@ -0,0 +1,51 @@ +addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Disable plugin $name"); + if (!strpos($name, '/')) { + $output->writeln('Bad name, name must contain character \'/\' , for example foo/MyAdmin'); + return self::FAILURE; + } + $config_file = config_path() . "/plugin/$name/app.php"; + if (!is_file($config_file)) { + return self::SUCCESS; + } + $config = include $config_file; + if (empty($config['enable'])) { + return self::SUCCESS; + } + $config_content = file_get_contents($config_file); + $config_content = preg_replace('/(\'enable\' *?=> *?)(true)/', '$1false', $config_content); + file_put_contents($config_file, $config_content); + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/PluginEnableCommand.php b/cacme/vendor/webman/console/src/Commands/PluginEnableCommand.php new file mode 100644 index 0000000..708dbcc --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/PluginEnableCommand.php @@ -0,0 +1,56 @@ +addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Enable plugin $name"); + if (!strpos($name, '/')) { + $output->writeln('Bad name, name must contain character \'/\' , for example foo/MyAdmin'); + return self::FAILURE; + } + $config_file = config_path() . "/plugin/$name/app.php"; + if (!is_file($config_file)) { + $output->writeln("$config_file not found"); + return self::FAILURE; + } + $config = include $config_file; + if (!isset($config['enable'])) { + $output->writeln("Config key 'enable' not found"); + return self::FAILURE; + } + if ($config['enable']) { + return self::SUCCESS; + } + $config_content = file_get_contents($config_file); + $config_content = preg_replace('/(\'enable\' *?=> *?)(false)/', '$1true', $config_content); + file_put_contents($config_file, $config_content); + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/PluginExportCommand.php b/cacme/vendor/webman/console/src/Commands/PluginExportCommand.php new file mode 100644 index 0000000..97d25a0 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/PluginExportCommand.php @@ -0,0 +1,152 @@ +addOption('name', 'name', InputOption::VALUE_REQUIRED, 'Plugin name, for example foo/my-admin'); + $this->addOption('source', 'source', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Directories to export'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $output->writeln('Export Plugin'); + $name = strtolower($input->getOption('name')); + if (!strpos($name, '/')) { + $output->writeln('Bad name, name must contain character \'/\' , for example foo/MyAdmin'); + return self::INVALID; + } + $namespace = Util::nameToNamespace($name); + $path_relations = $input->getOption('source'); + if (!in_array("config/plugin/$name", $path_relations)) { + if (is_dir("config/plugin/$name")) { + $path_relations[] = "config/plugin/$name"; + } + } + $original_dest = $dest = base_path()."/vendor/$name"; + $dest .= '/src'; + $this->writeInstallFile($namespace, $path_relations, $dest); + $output->writeln("Create $dest/Install.php"); + foreach ($path_relations as $source) { + $base_path = pathinfo("$dest/$source", PATHINFO_DIRNAME); + if (!is_dir($base_path)) { + mkdir($base_path, 0777, true); + } + $output->writeln("Copy $source to $dest/$source "); + copy_dir($source, "$dest/$source"); + } + $output->writeln("Saved $name to $original_dest"); + return self::SUCCESS; + } + + /** + * @param $namespace + * @param $path_relations + * @param $dest_dir + * @return void + */ + protected function writeInstallFile($namespace, $path_relations, $dest_dir) + { + if (!is_dir($dest_dir)) { + mkdir($dest_dir, 0777, true); + } + $relations = []; + foreach($path_relations as $relation) { + $relations[$relation] = $relation; + } + $relations = var_export($relations, true); + $install_php_content = << \$dest) { + if (\$pos = strrpos(\$dest, '/')) { + \$parent_dir = base_path().'/'.substr(\$dest, 0, \$pos); + if (!is_dir(\$parent_dir)) { + mkdir(\$parent_dir, 0777, true); + } + } + //symlink(__DIR__ . "/\$source", base_path()."/\$dest"); + copy_dir(__DIR__ . "/\$source", base_path()."/\$dest"); + echo "Create \$dest\r\n"; + } + } + + /** + * uninstallByRelation + * @return void + */ + public static function uninstallByRelation() + { + foreach (static::\$pathRelation as \$source => \$dest) { + \$path = base_path()."/\$dest"; + if (!is_dir(\$path) && !is_file(\$path)) { + continue; + } + echo "Remove \$dest\r\n"; + if (is_file(\$path) || is_link(\$path)) { + unlink(\$path); + continue; + } + remove_dir(\$path); + } + } + +} +EOT; + file_put_contents("$dest_dir/Install.php", $install_php_content); + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/PluginInstallCommand.php b/cacme/vendor/webman/console/src/Commands/PluginInstallCommand.php new file mode 100644 index 0000000..9a65e59 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/PluginInstallCommand.php @@ -0,0 +1,43 @@ +addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Execute installation for plugin $name"); + $namespace = Util::nameToNamespace($name); + $install_function = "\\{$namespace}\\Install::install"; + $plugin_const = "\\{$namespace}\\Install::WEBMAN_PLUGIN"; + if (defined($plugin_const) && is_callable($install_function)) { + $install_function(); + } + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/PluginUninstallCommand.php b/cacme/vendor/webman/console/src/Commands/PluginUninstallCommand.php new file mode 100644 index 0000000..4b99db3 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/PluginUninstallCommand.php @@ -0,0 +1,47 @@ +addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument('name'); + $output->writeln("Execute uninstall for plugin $name"); + if (!strpos($name, '/')) { + $output->writeln('Bad name, name must contain character \'/\' , for example foo/MyAdmin'); + return self::FAILURE; + } + $namespace = Util::nameToNamespace($name); + $uninstall_function = "\\{$namespace}\\Install::uninstall"; + $plugin_const = "\\{$namespace}\\Install::WEBMAN_PLUGIN"; + if (defined($plugin_const) && is_callable($uninstall_function)) { + $uninstall_function(); + } + return self::SUCCESS; + } + +} diff --git a/cacme/vendor/webman/console/src/Commands/ReStartCommand.php b/cacme/vendor/webman/console/src/Commands/ReStartCommand.php new file mode 100644 index 0000000..720cb0d --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/ReStartCommand.php @@ -0,0 +1,37 @@ +addOption('daemon', 'd', InputOption::VALUE_NONE, 'DAEMON mode') + ->addOption('graceful', 'g', InputOption::VALUE_NONE, 'graceful stop'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (\class_exists(\Support\App::class)) { + \Support\App::run(); + return self::SUCCESS; + } + Application::run(); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/ReloadCommand.php b/cacme/vendor/webman/console/src/Commands/ReloadCommand.php new file mode 100644 index 0000000..db2f2ce --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/ReloadCommand.php @@ -0,0 +1,36 @@ +addOption('graceful', 'd', InputOption::VALUE_NONE, 'graceful reload'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (\class_exists(\Support\App::class)) { + \Support\App::run(); + return self::SUCCESS; + } + Application::run(); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/RouteListCommand.php b/cacme/vendor/webman/console/src/Commands/RouteListCommand.php new file mode 100644 index 0000000..b6cbd10 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/RouteListCommand.php @@ -0,0 +1,39 @@ +getMethods() as $method) { + $cb = $route->getCallback(); + $cb = $cb instanceof \Closure ? 'Closure' : (is_array($cb) ? json_encode($cb) : var_export($cb, 1)); + $rows[] = [$route->getPath(), $method, $cb, json_encode($route->getMiddleware() ?: null), $route->getName()]; + } + } + + $table = new Table($output); + $table->setHeaders($headers); + $table->setRows($rows); + $table->render(); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/StartCommand.php b/cacme/vendor/webman/console/src/Commands/StartCommand.php new file mode 100644 index 0000000..5f7bdba --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/StartCommand.php @@ -0,0 +1,35 @@ +addOption('daemon', 'd', InputOption::VALUE_NONE, 'DAEMON mode'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (\class_exists(\Support\App::class)) { + \Support\App::run(); + return self::SUCCESS; + } + Application::run(); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/StatusCommand.php b/cacme/vendor/webman/console/src/Commands/StatusCommand.php new file mode 100644 index 0000000..534dcb5 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/StatusCommand.php @@ -0,0 +1,35 @@ +addOption('live', 'd', InputOption::VALUE_NONE, 'show live status'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (\class_exists(\Support\App::class)) { + \Support\App::run(); + return self::SUCCESS; + } + Application::run(); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/StopCommand.php b/cacme/vendor/webman/console/src/Commands/StopCommand.php new file mode 100644 index 0000000..5f1ed68 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/StopCommand.php @@ -0,0 +1,34 @@ +addOption('graceful', 'g',InputOption::VALUE_NONE, 'graceful stop'); + } + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (\class_exists(\Support\App::class)) { + \Support\App::run(); + return self::SUCCESS; + } + Application::run(); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Commands/VersionCommand.php b/cacme/vendor/webman/console/src/Commands/VersionCommand.php new file mode 100644 index 0000000..6e41574 --- /dev/null +++ b/cacme/vendor/webman/console/src/Commands/VersionCommand.php @@ -0,0 +1,29 @@ +writeln("Webman-framework $webman_framework_version"); + return self::SUCCESS; + } +} diff --git a/cacme/vendor/webman/console/src/Install.php b/cacme/vendor/webman/console/src/Install.php new file mode 100644 index 0000000..4fc1f51 --- /dev/null +++ b/cacme/vendor/webman/console/src/Install.php @@ -0,0 +1,76 @@ + 'config/plugin/webman/console', + ]; + + /** + * Install + * @return void + */ + public static function install() + { + $dest = base_path() . "/webman"; + if (is_dir($dest)) { + echo "Installation failed, please remove directory $dest\n"; + return; + } + copy(__DIR__ . "/webman", $dest); + chmod(base_path() . "/webman", 0755); + + static::installByRelation(); + } + + /** + * Uninstall + * @return void + */ + public static function uninstall() + { + if (is_file(base_path()."/webman")) { + unlink(base_path() . "/webman"); + } + self::uninstallByRelation(); + } + + /** + * installByRelation + * @return void + */ + public static function installByRelation() + { + foreach (static::$pathRelation as $source => $dest) { + if ($pos = strrpos($dest, '/')) { + $parent_dir = base_path().'/'.substr($dest, 0, $pos); + if (!is_dir($parent_dir)) { + mkdir($parent_dir, 0777, true); + } + } + copy_dir(__DIR__ . "/$source", base_path()."/$dest"); + } + } + + /** + * uninstallByRelation + * @return void + */ + public static function uninstallByRelation() + { + foreach (static::$pathRelation as $source => $dest) { + $path = base_path()."/$dest"; + if (!is_dir($path) && !is_file($path)) { + continue; + } + remove_dir($path); + } + } + +} diff --git a/cacme/vendor/webman/console/src/Util.php b/cacme/vendor/webman/console/src/Util.php new file mode 100644 index 0000000..bd20b12 --- /dev/null +++ b/cacme/vendor/webman/console/src/Util.php @@ -0,0 +1,66 @@ + true, + + 'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build', + + 'phar_filename' => 'webman.phar', + + 'bin_filename' => 'webman.bin', + + 'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL. + + 'private_key_file' => '', // The file path for certificate or OpenSSL private key file. + + 'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#', + + 'exclude_files' => [ + '.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin' + ], + + 'custom_ini' => ' +memory_limit = 256M + ', +]; diff --git a/cacme/vendor/webman/console/src/webman b/cacme/vendor/webman/console/src/webman new file mode 100755 index 0000000..69758c1 --- /dev/null +++ b/cacme/vendor/webman/console/src/webman @@ -0,0 +1,57 @@ +#!/usr/bin/env php +setName('webman cli'); +$cli->installInternalCommands(); +if (is_dir($command_path = Util::guessPath(app_path(), '/command', true))) { + $cli->installCommands($command_path); +} + +foreach (config('plugin', []) as $firm => $projects) { + if (isset($projects['app'])) { + if ($command_str = Util::guessPath(base_path() . "/plugin/$firm", 'command')) { + $command_path = base_path() . "/plugin/$firm/$command_str"; + $cli->installCommands($command_path, "plugin\\$firm\\$command_str"); + } + } + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['command'] ?? [] as $class_name) { + $reflection = new \ReflectionClass($class_name); + if ($reflection->isAbstract()) { + continue; + } + $properties = $reflection->getStaticProperties(); + $name = $properties['defaultName']; + if (!$name) { + throw new RuntimeException("Command {$class_name} has no defaultName"); + } + $description = $properties['defaultDescription'] ?? ''; + $command = Container::get($class_name); + $command->setName($name)->setDescription($description); + $cli->add($command); + } + } +} + +$cli->run(); diff --git a/cacme/vendor/webmozart/assert/CHANGELOG.md b/cacme/vendor/webmozart/assert/CHANGELOG.md new file mode 100644 index 0000000..56c8011 --- /dev/null +++ b/cacme/vendor/webmozart/assert/CHANGELOG.md @@ -0,0 +1,207 @@ +Changelog +========= + +## UNRELEASED + +## 1.11.0 + +### Added + +* Added explicit (non magic) `allNullOr*` methods, with `@psalm-assert` annotations, for better Psalm support. + +### Changed + +* Trait methods will now check the assertion themselves, instead of using `__callStatic` +* `isList` will now deal correctly with (modified) lists that contain `NaN` +* `reportInvalidArgument` now has a return type of `never`. + +### Removed + +* Removed `symfony/polyfill-ctype` as a dependency, and require `ext-cytpe` instead. + * You can still require the `symfony/polyfill-ctype` in your project if you need it, as it provides `ext-ctype` + +## 1.10.0 + +### Added + +* On invalid assertion, we throw a `Webmozart\Assert\InvalidArgumentException` +* Added `Assert::positiveInteger()` + +### Changed + +* Using a trait with real implementations of `all*()` and `nullOr*()` methods to improve psalm compatibility. + +### Removed + +* Support for PHP <7.2 + +## 1.9.1 + +## Fixed + +* provisional support for PHP 8.0 + +## 1.9.0 + +* added better Psalm support for `all*` & `nullOr*` methods +* These methods are now understood by Psalm through a mixin. You may need a newer version of Psalm in order to use this +* added `@psalm-pure` annotation to `Assert::notFalse()` +* added more `@psalm-assert` annotations where appropriate + +## Changed + +* the `all*` & `nullOr*` methods are now declared on an interface, instead of `@method` annotations. +This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDE's have supported this +for a long time, and you should not lose any autocompletion capabilities. PHPStan has supported this since +version `0.12.20`. This package is marked incompatible (with a composer conflict) with phpstan version prior to that. +If you do not use PHPStan than this does not matter. + +## 1.8.0 + +### Added + +* added `Assert::notStartsWith()` +* added `Assert::notEndsWith()` +* added `Assert::inArray()` +* added `@psalm-pure` annotations to pure assertions + +### Fixed + +* Exception messages of comparisons between `DateTime(Immutable)` objects now display their date & time. +* Custom Exception messages for `Assert::count()` now use the values to render the exception message. + +## 1.7.0 (2020-02-14) + +### Added + +* added `Assert::notFalse()` +* added `Assert::isAOf()` +* added `Assert::isAnyOf()` +* added `Assert::isNotA()` + +## 1.6.0 (2019-11-24) + +### Added + +* added `Assert::validArrayKey()` +* added `Assert::isNonEmptyList()` +* added `Assert::isNonEmptyMap()` +* added `@throws InvalidArgumentException` annotations to all methods that throw. +* added `@psalm-assert` for the list type to the `isList` assertion. + +### Fixed + +* `ResourceBundle` & `SimpleXMLElement` now pass the `isCountable` assertions. +They are countable, without implementing the `Countable` interface. +* The doc block of `range` now has the proper variables. +* An empty array will now pass `isList` and `isMap`. As it is a valid form of both. +If a non-empty variant is needed, use `isNonEmptyList` or `isNonEmptyMap`. + +### Changed + +* Removed some `@psalm-assert` annotations, that were 'side effect' assertions See: + * [#144](https://github.com/webmozart/assert/pull/144) + * [#145](https://github.com/webmozart/assert/issues/145) + * [#146](https://github.com/webmozart/assert/pull/146) + * [#150](https://github.com/webmozart/assert/pull/150) +* If you use Psalm, the minimum version needed is `3.6.0`. Which is enforced through a composer conflict. +If you don't use Psalm, then this has no impact. + +## 1.5.0 (2019-08-24) + +### Added + +* added `Assert::uniqueValues()` +* added `Assert::unicodeLetters()` +* added: `Assert::email()` +* added support for [Psalm](https://github.com/vimeo/psalm), by adding `@psalm-assert` annotations where appropriate. + +### Fixed + +* `Assert::endsWith()` would not give the correct result when dealing with a multibyte suffix. +* `Assert::length(), minLength, maxLength, lengthBetween` would not give the correct result when dealing with multibyte characters. + +**NOTE**: These 2 changes may break your assertions if you relied on the fact that multibyte characters didn't behave correctly. + +### Changed + +* The names of some variables have been updated to better reflect what they are. +* All function calls are now in their FQN form, slightly increasing performance. +* Tests are now properly ran against HHVM-3.30 and PHP nightly. + +### Deprecation + +* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()` + * This was already done in 1.3.0, but it was only done through a silenced `trigger_error`. It is now annotated as well. + +## 1.4.0 (2018-12-25) + +### Added + +* added `Assert::ip()` +* added `Assert::ipv4()` +* added `Assert::ipv6()` +* added `Assert::notRegex()` +* added `Assert::interfaceExists()` +* added `Assert::isList()` +* added `Assert::isMap()` +* added polyfill for ctype + +### Fixed + +* Special case when comparing objects implementing `__toString()` + +## 1.3.0 (2018-01-29) + +### Added + +* added `Assert::minCount()` +* added `Assert::maxCount()` +* added `Assert::countBetween()` +* added `Assert::isCountable()` +* added `Assert::notWhitespaceOnly()` +* added `Assert::natural()` +* added `Assert::notContains()` +* added `Assert::isArrayAccessible()` +* added `Assert::isInstanceOfAny()` +* added `Assert::isIterable()` + +### Fixed + +* `stringNotEmpty` will no longer report "0" is an empty string + +### Deprecation + +* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()` + +## 1.2.0 (2016-11-23) + + * added `Assert::throws()` + * added `Assert::count()` + * added extension point `Assert::reportInvalidArgument()` for custom subclasses + +## 1.1.0 (2016-08-09) + + * added `Assert::object()` + * added `Assert::propertyExists()` + * added `Assert::propertyNotExists()` + * added `Assert::methodExists()` + * added `Assert::methodNotExists()` + * added `Assert::uuid()` + +## 1.0.2 (2015-08-24) + + * integrated Style CI + * add tests for minimum package dependencies on Travis CI + +## 1.0.1 (2015-05-12) + + * added support for PHP 5.3.3 + +## 1.0.0 (2015-05-12) + + * first stable release + +## 1.0.0-beta (2015-03-19) + + * first beta release diff --git a/cacme/vendor/webmozart/assert/LICENSE b/cacme/vendor/webmozart/assert/LICENSE new file mode 100644 index 0000000..9e2e307 --- /dev/null +++ b/cacme/vendor/webmozart/assert/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Bernhard Schussek + +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/cacme/vendor/webmozart/assert/README.md b/cacme/vendor/webmozart/assert/README.md new file mode 100644 index 0000000..3b2397a --- /dev/null +++ b/cacme/vendor/webmozart/assert/README.md @@ -0,0 +1,287 @@ +Webmozart Assert +================ + +[![Latest Stable Version](https://poser.pugx.org/webmozart/assert/v/stable.svg)](https://packagist.org/packages/webmozart/assert) +[![Total Downloads](https://poser.pugx.org/webmozart/assert/downloads.svg)](https://packagist.org/packages/webmozart/assert) + +This library contains efficient assertions to test the input and output of +your methods. With these assertions, you can greatly reduce the amount of coding +needed to write a safe implementation. + +All assertions in the [`Assert`] class throw an `Webmozart\Assert\InvalidArgumentException` if +they fail. + +FAQ +--- + +**What's the difference to [beberlei/assert]?** + +This library is heavily inspired by Benjamin Eberlei's wonderful [assert package], +but fixes a usability issue with error messages that can't be fixed there without +breaking backwards compatibility. + +This package features usable error messages by default. However, you can also +easily write custom error messages: + +``` +Assert::string($path, 'The path is expected to be a string. Got: %s'); +``` + +In [beberlei/assert], the ordering of the `%s` placeholders is different for +every assertion. This package, on the contrary, provides consistent placeholder +ordering for all assertions: + +* `%s`: The tested value as string, e.g. `"/foo/bar"`. +* `%2$s`, `%3$s`, ...: Additional assertion-specific values, e.g. the + minimum/maximum length, allowed values, etc. + +Check the source code of the assertions to find out details about the additional +available placeholders. + +Installation +------------ + +Use [Composer] to install the package: + +```bash +composer require webmozart/assert +``` + +Example +------- + +```php +use Webmozart\Assert\Assert; + +class Employee +{ + public function __construct($id) + { + Assert::integer($id, 'The employee ID must be an integer. Got: %s'); + Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s'); + } +} +``` + +If you create an employee with an invalid ID, an exception is thrown: + +```php +new Employee('foobar'); +// => Webmozart\Assert\InvalidArgumentException: +// The employee ID must be an integer. Got: string + +new Employee(-10); +// => Webmozart\Assert\InvalidArgumentException: +// The employee ID must be a positive integer. Got: -10 +``` + +Assertions +---------- + +The [`Assert`] class provides the following assertions: + +### Type Assertions + +Method | Description +-------------------------------------------------------- | -------------------------------------------------- +`string($value, $message = '')` | Check that a value is a string +`stringNotEmpty($value, $message = '')` | Check that a value is a non-empty string +`integer($value, $message = '')` | Check that a value is an integer +`integerish($value, $message = '')` | Check that a value casts to an integer +`positiveInteger($value, $message = '')` | Check that a value is a positive (non-zero) integer +`float($value, $message = '')` | Check that a value is a float +`numeric($value, $message = '')` | Check that a value is numeric +`natural($value, $message= ''')` | Check that a value is a non-negative integer +`boolean($value, $message = '')` | Check that a value is a boolean +`scalar($value, $message = '')` | Check that a value is a scalar +`object($value, $message = '')` | Check that a value is an object +`resource($value, $type = null, $message = '')` | Check that a value is a resource +`isCallable($value, $message = '')` | Check that a value is a callable +`isArray($value, $message = '')` | Check that a value is an array +`isTraversable($value, $message = '')` (deprecated) | Check that a value is an array or a `\Traversable` +`isIterable($value, $message = '')` | Check that a value is an array or a `\Traversable` +`isCountable($value, $message = '')` | Check that a value is an array or a `\Countable` +`isInstanceOf($value, $class, $message = '')` | Check that a value is an `instanceof` a class +`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes +`notInstanceOf($value, $class, $message = '')` | Check that a value is not an `instanceof` a class +`isAOf($value, $class, $message = '')` | Check that a value is of the class or has one of its parents +`isAnyOf($value, array $classes, $message = '')` | Check that a value is of at least one of the classes or has one of its parents +`isNotA($value, $class, $message = '')` | Check that a value is not of the class or has not one of its parents +`isArrayAccessible($value, $message = '')` | Check that a value can be accessed as an array +`uniqueValues($values, $message = '')` | Check that the given array contains unique values + +### Comparison Assertions + +Method | Description +----------------------------------------------- | ------------------------------------------------------------------ +`true($value, $message = '')` | Check that a value is `true` +`false($value, $message = '')` | Check that a value is `false` +`notFalse($value, $message = '')` | Check that a value is not `false` +`null($value, $message = '')` | Check that a value is `null` +`notNull($value, $message = '')` | Check that a value is not `null` +`isEmpty($value, $message = '')` | Check that a value is `empty()` +`notEmpty($value, $message = '')` | Check that a value is not `empty()` +`eq($value, $value2, $message = '')` | Check that a value equals another (`==`) +`notEq($value, $value2, $message = '')` | Check that a value does not equal another (`!=`) +`same($value, $value2, $message = '')` | Check that a value is identical to another (`===`) +`notSame($value, $value2, $message = '')` | Check that a value is not identical to another (`!==`) +`greaterThan($value, $value2, $message = '')` | Check that a value is greater than another +`greaterThanEq($value, $value2, $message = '')` | Check that a value is greater than or equal to another +`lessThan($value, $value2, $message = '')` | Check that a value is less than another +`lessThanEq($value, $value2, $message = '')` | Check that a value is less than or equal to another +`range($value, $min, $max, $message = '')` | Check that a value is within a range +`inArray($value, array $values, $message = '')` | Check that a value is one of a list of values +`oneOf($value, array $values, $message = '')` | Check that a value is one of a list of values (alias of `inArray`) + +### String Assertions + +You should check that a value is a string with `Assert::string()` before making +any of the following assertions. + +Method | Description +--------------------------------------------------- | ----------------------------------------------------------------- +`contains($value, $subString, $message = '')` | Check that a string contains a substring +`notContains($value, $subString, $message = '')` | Check that a string does not contain a substring +`startsWith($value, $prefix, $message = '')` | Check that a string has a prefix +`notStartsWith($value, $prefix, $message = '')` | Check that a string does not have a prefix +`startsWithLetter($value, $message = '')` | Check that a string starts with a letter +`endsWith($value, $suffix, $message = '')` | Check that a string has a suffix +`notEndsWith($value, $suffix, $message = '')` | Check that a string does not have a suffix +`regex($value, $pattern, $message = '')` | Check that a string matches a regular expression +`notRegex($value, $pattern, $message = '')` | Check that a string does not match a regular expression +`unicodeLetters($value, $message = '')` | Check that a string contains Unicode letters only +`alpha($value, $message = '')` | Check that a string contains letters only +`digits($value, $message = '')` | Check that a string contains digits only +`alnum($value, $message = '')` | Check that a string contains letters and digits only +`lower($value, $message = '')` | Check that a string contains lowercase characters only +`upper($value, $message = '')` | Check that a string contains uppercase characters only +`length($value, $length, $message = '')` | Check that a string has a certain number of characters +`minLength($value, $min, $message = '')` | Check that a string has at least a certain number of characters +`maxLength($value, $max, $message = '')` | Check that a string has at most a certain number of characters +`lengthBetween($value, $min, $max, $message = '')` | Check that a string has a length in the given range +`uuid($value, $message = '')` | Check that a string is a valid UUID +`ip($value, $message = '')` | Check that a string is a valid IP (either IPv4 or IPv6) +`ipv4($value, $message = '')` | Check that a string is a valid IPv4 +`ipv6($value, $message = '')` | Check that a string is a valid IPv6 +`email($value, $message = '')` | Check that a string is a valid e-mail address +`notWhitespaceOnly($value, $message = '')` | Check that a string contains at least one non-whitespace character + +### File Assertions + +Method | Description +----------------------------------- | -------------------------------------------------- +`fileExists($value, $message = '')` | Check that a value is an existing path +`file($value, $message = '')` | Check that a value is an existing file +`directory($value, $message = '')` | Check that a value is an existing directory +`readable($value, $message = '')` | Check that a value is a readable path +`writable($value, $message = '')` | Check that a value is a writable path + +### Object Assertions + +Method | Description +----------------------------------------------------- | -------------------------------------------------- +`classExists($value, $message = '')` | Check that a value is an existing class name +`subclassOf($value, $class, $message = '')` | Check that a class is a subclass of another +`interfaceExists($value, $message = '')` | Check that a value is an existing interface name +`implementsInterface($value, $class, $message = '')` | Check that a class implements an interface +`propertyExists($value, $property, $message = '')` | Check that a property exists in a class/object +`propertyNotExists($value, $property, $message = '')` | Check that a property does not exist in a class/object +`methodExists($value, $method, $message = '')` | Check that a method exists in a class/object +`methodNotExists($value, $method, $message = '')` | Check that a method does not exist in a class/object + +### Array Assertions + +Method | Description +-------------------------------------------------- | ------------------------------------------------------------------ +`keyExists($array, $key, $message = '')` | Check that a key exists in an array +`keyNotExists($array, $key, $message = '')` | Check that a key does not exist in an array +`validArrayKey($key, $message = '')` | Check that a value is a valid array key (int or string) +`count($array, $number, $message = '')` | Check that an array contains a specific number of elements +`minCount($array, $min, $message = '')` | Check that an array contains at least a certain number of elements +`maxCount($array, $max, $message = '')` | Check that an array contains at most a certain number of elements +`countBetween($array, $min, $max, $message = '')` | Check that an array has a count in the given range +`isList($array, $message = '')` | Check that an array is a non-associative list +`isNonEmptyList($array, $message = '')` | Check that an array is a non-associative list, and not empty +`isMap($array, $message = '')` | Check that an array is associative and has strings as keys +`isNonEmptyMap($array, $message = '')` | Check that an array is associative and has strings as keys, and is not empty + +### Function Assertions + +Method | Description +------------------------------------------- | ----------------------------------------------------------------------------------------------------- +`throws($closure, $class, $message = '')` | Check that a function throws a certain exception. Subclasses of the exception class will be accepted. + +### Collection Assertions + +All of the above assertions can be prefixed with `all*()` to test the contents +of an array or a `\Traversable`: + +```php +Assert::allIsInstanceOf($employees, 'Acme\Employee'); +``` + +### Nullable Assertions + +All of the above assertions can be prefixed with `nullOr*()` to run the +assertion only if it the value is not `null`: + +```php +Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s'); +``` + +### Extending Assert + +The `Assert` class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to +add your own assertions. + +#### Overriding methods + +Overriding the following methods in your assertion class allows you to change the behaviour of the assertions: + +* `public static function __callStatic($name, $arguments)` + * This method is used to 'create' the `nullOr` and `all` versions of the assertions. +* `protected static function valueToString($value)` + * This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a `__toString` method for example. +* `protected static function typeToString($value)` + * This method is used for error messages, to convert the a value to a string representing its type. +* `protected static function strlen($value)` + * This method is used to calculate string length for relevant methods, using the `mb_strlen` if available and useful. +* `protected static function reportInvalidArgument($message)` + * This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something. + +## Static analysis support + +Where applicable, assertion functions are annotated to support Psalm's +[Assertion syntax](https://psalm.dev/docs/annotating_code/assertion_syntax/). +A dedicated [PHPStan Plugin](https://github.com/phpstan/phpstan-webmozart-assert) is +required for proper type support. + +Authors +------- + +* [Bernhard Schussek] a.k.a. [@webmozart] +* [The Community Contributors] + +Contribute +---------- + +Contributions to the package are always welcome! + +* Report any bugs or issues you find on the [issue tracker]. +* You can grab the source code at the package's [Git repository]. + +License +------- + +All contents of this package are licensed under the [MIT license]. + +[beberlei/assert]: https://github.com/beberlei/assert +[assert package]: https://github.com/beberlei/assert +[Composer]: https://getcomposer.org +[Bernhard Schussek]: https://webmozarts.com +[The Community Contributors]: https://github.com/webmozart/assert/graphs/contributors +[issue tracker]: https://github.com/webmozart/assert/issues +[Git repository]: https://github.com/webmozart/assert +[@webmozart]: https://twitter.com/webmozart +[MIT license]: LICENSE +[`Assert`]: src/Assert.php diff --git a/cacme/vendor/webmozart/assert/composer.json b/cacme/vendor/webmozart/assert/composer.json new file mode 100644 index 0000000..b340452 --- /dev/null +++ b/cacme/vendor/webmozart/assert/composer.json @@ -0,0 +1,43 @@ +{ + "name": "webmozart/assert", + "description": "Assertions to validate method input/output with nice error messages.", + "license": "MIT", + "keywords": [ + "assert", + "check", + "validate" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "require": { + "php": "^7.2 || ^8.0", + "ext-ctype": "*" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Webmozart\\Assert\\Tests\\": "tests/", + "Webmozart\\Assert\\Bin\\": "bin/src" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + } +} diff --git a/cacme/vendor/webmozart/assert/src/Assert.php b/cacme/vendor/webmozart/assert/src/Assert.php new file mode 100644 index 0000000..db1f3a5 --- /dev/null +++ b/cacme/vendor/webmozart/assert/src/Assert.php @@ -0,0 +1,2080 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webmozart\Assert; + +use ArrayAccess; +use BadMethodCallException; +use Closure; +use Countable; +use DateTime; +use DateTimeImmutable; +use Exception; +use ResourceBundle; +use SimpleXMLElement; +use Throwable; +use Traversable; + +/** + * Efficient assertions to validate the input/output of your methods. + * + * @since 1.0 + * + * @author Bernhard Schussek + */ +class Assert +{ + use Mixin; + + /** + * @psalm-pure + * @psalm-assert string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function string($value, $message = '') + { + if (!\is_string($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a string. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function stringNotEmpty($value, $message = '') + { + static::string($value, $message); + static::notEq($value, '', $message); + } + + /** + * @psalm-pure + * @psalm-assert int $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function integer($value, $message = '') + { + if (!\is_int($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an integer. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert numeric $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function integerish($value, $message = '') + { + if (!\is_numeric($value) || $value != (int) $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an integerish value. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert positive-int $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function positiveInteger($value, $message = '') + { + if (!(\is_int($value) && $value > 0)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a positive integer. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert float $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function float($value, $message = '') + { + if (!\is_float($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a float. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert numeric $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function numeric($value, $message = '') + { + if (!\is_numeric($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a numeric. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert positive-int|0 $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function natural($value, $message = '') + { + if (!\is_int($value) || $value < 0) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a non-negative integer. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert bool $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function boolean($value, $message = '') + { + if (!\is_bool($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a boolean. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert scalar $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function scalar($value, $message = '') + { + if (!\is_scalar($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a scalar. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert object $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function object($value, $message = '') + { + if (!\is_object($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an object. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert resource $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function resource($value, $type = null, $message = '') + { + if (!\is_resource($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a resource. Got: %s', + static::typeToString($value) + )); + } + + if ($type && $type !== \get_resource_type($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a resource of type %2$s. Got: %s', + static::typeToString($value), + $type + )); + } + } + + /** + * @psalm-pure + * @psalm-assert callable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isCallable($value, $message = '') + { + if (!\is_callable($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a callable. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert array $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isArray($value, $message = '') + { + if (!\is_array($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isTraversable($value, $message = '') + { + @\trigger_error( + \sprintf( + 'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', + __METHOD__ + ), + \E_USER_DEPRECATED + ); + + if (!\is_array($value) && !($value instanceof Traversable)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a traversable. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert array|ArrayAccess $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isArrayAccessible($value, $message = '') + { + if (!\is_array($value) && !($value instanceof ArrayAccess)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array accessible. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert countable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isCountable($value, $message = '') + { + if ( + !\is_array($value) + && !($value instanceof Countable) + && !($value instanceof ResourceBundle) + && !($value instanceof SimpleXMLElement) + ) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a countable. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isIterable($value, $message = '') + { + if (!\is_array($value) && !($value instanceof Traversable)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an iterable. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert ExpectedType $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isInstanceOf($value, $class, $message = '') + { + if (!($value instanceof $class)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an instance of %2$s. Got: %s', + static::typeToString($value), + $class + )); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert !ExpectedType $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notInstanceOf($value, $class, $message = '') + { + if ($value instanceof $class) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an instance other than %2$s. Got: %s', + static::typeToString($value), + $class + )); + } + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param mixed $value + * @param array $classes + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isInstanceOfAny($value, array $classes, $message = '') + { + foreach ($classes as $class) { + if ($value instanceof $class) { + return; + } + } + + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an instance of any of %2$s. Got: %s', + static::typeToString($value), + \implode(', ', \array_map(array(static::class, 'valueToString'), $classes)) + )); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert ExpectedType|class-string $value + * + * @param object|string $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isAOf($value, $class, $message = '') + { + static::string($class, 'Expected class as a string. Got: %s'); + + if (!\is_a($value, $class, \is_string($value))) { + static::reportInvalidArgument(sprintf( + $message ?: 'Expected an instance of this class or to this class among its parents "%2$s". Got: %s', + static::valueToString($value), + $class + )); + } + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string $class + * @psalm-assert !UnexpectedType $value + * @psalm-assert !class-string $value + * + * @param object|string $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isNotA($value, $class, $message = '') + { + static::string($class, 'Expected class as a string. Got: %s'); + + if (\is_a($value, $class, \is_string($value))) { + static::reportInvalidArgument(sprintf( + $message ?: 'Expected an instance of this class or to this class among its parents other than "%2$s". Got: %s', + static::valueToString($value), + $class + )); + } + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param object|string $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isAnyOf($value, array $classes, $message = '') + { + foreach ($classes as $class) { + static::string($class, 'Expected class as a string. Got: %s'); + + if (\is_a($value, $class, \is_string($value))) { + return; + } + } + + static::reportInvalidArgument(sprintf( + $message ?: 'Expected an instance of any of this classes or any of those classes among their parents "%2$s". Got: %s', + static::valueToString($value), + \implode(', ', $classes) + )); + } + + /** + * @psalm-pure + * @psalm-assert empty $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isEmpty($value, $message = '') + { + if (!empty($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an empty value. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert !empty $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notEmpty($value, $message = '') + { + if (empty($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a non-empty value. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function null($value, $message = '') + { + if (null !== $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected null. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert !null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notNull($value, $message = '') + { + if (null === $value) { + static::reportInvalidArgument( + $message ?: 'Expected a value other than null.' + ); + } + } + + /** + * @psalm-pure + * @psalm-assert true $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function true($value, $message = '') + { + if (true !== $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be true. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert false $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function false($value, $message = '') + { + if (false !== $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be false. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert !false $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notFalse($value, $message = '') + { + if (false === $value) { + static::reportInvalidArgument( + $message ?: 'Expected a value other than false.' + ); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function ip($value, $message = '') + { + if (false === \filter_var($value, \FILTER_VALIDATE_IP)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be an IP. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function ipv4($value, $message = '') + { + if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be an IPv4. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function ipv6($value, $message = '') + { + if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be an IPv6. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function email($value, $message = '') + { + if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be a valid e-mail address. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion. + * + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function uniqueValues(array $values, $message = '') + { + $allValues = \count($values); + $uniqueValues = \count(\array_unique($values)); + + if ($allValues !== $uniqueValues) { + $difference = $allValues - $uniqueValues; + + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array of unique values, but %s of them %s duplicated', + $difference, + (1 === $difference ? 'is' : 'are') + )); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function eq($value, $expect, $message = '') + { + if ($expect != $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value equal to %2$s. Got: %s', + static::valueToString($value), + static::valueToString($expect) + )); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notEq($value, $expect, $message = '') + { + if ($expect == $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a different value than %s.', + static::valueToString($expect) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function same($value, $expect, $message = '') + { + if ($expect !== $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value identical to %2$s. Got: %s', + static::valueToString($value), + static::valueToString($expect) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notSame($value, $expect, $message = '') + { + if ($expect === $value) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value not identical to %s.', + static::valueToString($expect) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function greaterThan($value, $limit, $message = '') + { + if ($value <= $limit) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value greater than %2$s. Got: %s', + static::valueToString($value), + static::valueToString($limit) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function greaterThanEq($value, $limit, $message = '') + { + if ($value < $limit) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value greater than or equal to %2$s. Got: %s', + static::valueToString($value), + static::valueToString($limit) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function lessThan($value, $limit, $message = '') + { + if ($value >= $limit) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value less than %2$s. Got: %s', + static::valueToString($value), + static::valueToString($limit) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function lessThanEq($value, $limit, $message = '') + { + if ($value > $limit) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value less than or equal to %2$s. Got: %s', + static::valueToString($value), + static::valueToString($limit) + )); + } + } + + /** + * Inclusive range, so Assert::(3, 3, 5) passes. + * + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function range($value, $min, $max, $message = '') + { + if ($value < $min || $value > $max) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value between %2$s and %3$s. Got: %s', + static::valueToString($value), + static::valueToString($min), + static::valueToString($max) + )); + } + } + + /** + * A more human-readable alias of Assert::inArray(). + * + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function oneOf($value, array $values, $message = '') + { + static::inArray($value, $values, $message); + } + + /** + * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion. + * + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function inArray($value, array $values, $message = '') + { + if (!\in_array($value, $values, true)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected one of: %2$s. Got: %s', + static::valueToString($value), + \implode(', ', \array_map(array(static::class, 'valueToString'), $values)) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function contains($value, $subString, $message = '') + { + if (false === \strpos($value, $subString)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain %2$s. Got: %s', + static::valueToString($value), + static::valueToString($subString) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notContains($value, $subString, $message = '') + { + if (false !== \strpos($value, $subString)) { + static::reportInvalidArgument(\sprintf( + $message ?: '%2$s was not expected to be contained in a value. Got: %s', + static::valueToString($value), + static::valueToString($subString) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notWhitespaceOnly($value, $message = '') + { + if (\preg_match('/^\s*$/', $value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a non-whitespace string. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function startsWith($value, $prefix, $message = '') + { + if (0 !== \strpos($value, $prefix)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to start with %2$s. Got: %s', + static::valueToString($value), + static::valueToString($prefix) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notStartsWith($value, $prefix, $message = '') + { + if (0 === \strpos($value, $prefix)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value not to start with %2$s. Got: %s', + static::valueToString($value), + static::valueToString($prefix) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function startsWithLetter($value, $message = '') + { + static::string($value); + + $valid = isset($value[0]); + + if ($valid) { + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = \ctype_alpha($value[0]); + \setlocale(LC_CTYPE, $locale); + } + + if (!$valid) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to start with a letter. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function endsWith($value, $suffix, $message = '') + { + if ($suffix !== \substr($value, -\strlen($suffix))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to end with %2$s. Got: %s', + static::valueToString($value), + static::valueToString($suffix) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notEndsWith($value, $suffix, $message = '') + { + if ($suffix === \substr($value, -\strlen($suffix))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value not to end with %2$s. Got: %s', + static::valueToString($value), + static::valueToString($suffix) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function regex($value, $pattern, $message = '') + { + if (!\preg_match($pattern, $value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The value %s does not match the expected pattern.', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notRegex($value, $pattern, $message = '') + { + if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The value %s matches the pattern %s (at offset %d).', + static::valueToString($value), + static::valueToString($pattern), + $matches[0][1] + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function unicodeLetters($value, $message = '') + { + static::string($value); + + if (!\preg_match('/^\p{L}+$/u', $value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain only Unicode letters. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function alpha($value, $message = '') + { + static::string($value); + + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_alpha($value); + \setlocale(LC_CTYPE, $locale); + + if ($valid) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain only letters. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function digits($value, $message = '') + { + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_digit($value); + \setlocale(LC_CTYPE, $locale); + + if ($valid) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain digits only. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function alnum($value, $message = '') + { + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_alnum($value); + \setlocale(LC_CTYPE, $locale); + + if ($valid) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain letters and digits only. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert lowercase-string $value + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function lower($value, $message = '') + { + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_lower($value); + \setlocale(LC_CTYPE, $locale); + + if ($valid) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain lowercase characters only. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert !lowercase-string $value + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function upper($value, $message = '') + { + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_upper($value); + \setlocale(LC_CTYPE, $locale); + + if ($valid) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain uppercase characters only. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function length($value, $length, $message = '') + { + if ($length !== static::strlen($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain %2$s characters. Got: %s', + static::valueToString($value), + $length + )); + } + } + + /** + * Inclusive min. + * + * @psalm-pure + * + * @param string $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function minLength($value, $min, $message = '') + { + if (static::strlen($value) < $min) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain at least %2$s characters. Got: %s', + static::valueToString($value), + $min + )); + } + } + + /** + * Inclusive max. + * + * @psalm-pure + * + * @param string $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function maxLength($value, $max, $message = '') + { + if (static::strlen($value) > $max) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain at most %2$s characters. Got: %s', + static::valueToString($value), + $max + )); + } + } + + /** + * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion. + * + * @psalm-pure + * + * @param string $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function lengthBetween($value, $min, $max, $message = '') + { + $length = static::strlen($value); + + if ($length < $min || $length > $max) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', + static::valueToString($value), + $min, + $max + )); + } + } + + /** + * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file. + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function fileExists($value, $message = '') + { + static::string($value); + + if (!\file_exists($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The file %s does not exist.', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function file($value, $message = '') + { + static::fileExists($value, $message); + + if (!\is_file($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The path %s is not a file.', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function directory($value, $message = '') + { + static::fileExists($value, $message); + + if (!\is_dir($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The path %s is no directory.', + static::valueToString($value) + )); + } + } + + /** + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function readable($value, $message = '') + { + if (!\is_readable($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The path %s is not readable.', + static::valueToString($value) + )); + } + } + + /** + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function writable($value, $message = '') + { + if (!\is_writable($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The path %s is not writable.', + static::valueToString($value) + )); + } + } + + /** + * @psalm-assert class-string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function classExists($value, $message = '') + { + if (!\class_exists($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an existing class name. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert class-string|ExpectedType $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function subclassOf($value, $class, $message = '') + { + if (!\is_subclass_of($value, $class)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a sub-class of %2$s. Got: %s', + static::valueToString($value), + static::valueToString($class) + )); + } + } + + /** + * @psalm-assert class-string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function interfaceExists($value, $message = '') + { + if (!\interface_exists($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an existing interface name. got %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $interface + * @psalm-assert class-string $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function implementsInterface($value, $interface, $message = '') + { + if (!\in_array($interface, \class_implements($value))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an implementation of %2$s. Got: %s', + static::valueToString($value), + static::valueToString($interface) + )); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function propertyExists($classOrObject, $property, $message = '') + { + if (!\property_exists($classOrObject, $property)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected the property %s to exist.', + static::valueToString($property) + )); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function propertyNotExists($classOrObject, $property, $message = '') + { + if (\property_exists($classOrObject, $property)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected the property %s to not exist.', + static::valueToString($property) + )); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function methodExists($classOrObject, $method, $message = '') + { + if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected the method %s to exist.', + static::valueToString($method) + )); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function methodNotExists($classOrObject, $method, $message = '') + { + if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected the method %s to not exist.', + static::valueToString($method) + )); + } + } + + /** + * @psalm-pure + * + * @param array $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function keyExists($array, $key, $message = '') + { + if (!(isset($array[$key]) || \array_key_exists($key, $array))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected the key %s to exist.', + static::valueToString($key) + )); + } + } + + /** + * @psalm-pure + * + * @param array $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function keyNotExists($array, $key, $message = '') + { + if (isset($array[$key]) || \array_key_exists($key, $array)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected the key %s to not exist.', + static::valueToString($key) + )); + } + } + + /** + * Checks if a value is a valid array key (int or string). + * + * @psalm-pure + * @psalm-assert array-key $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function validArrayKey($value, $message = '') + { + if (!(\is_int($value) || \is_string($value))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected string or integer. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function count($array, $number, $message = '') + { + static::eq( + \count($array), + $number, + \sprintf( + $message ?: 'Expected an array to contain %d elements. Got: %d.', + $number, + \count($array) + ) + ); + } + + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function minCount($array, $min, $message = '') + { + if (\count($array) < $min) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array to contain at least %2$d elements. Got: %d', + \count($array), + $min + )); + } + } + + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function maxCount($array, $max, $message = '') + { + if (\count($array) > $max) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array to contain at most %2$d elements. Got: %d', + \count($array), + $max + )); + } + } + + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function countBetween($array, $min, $max, $message = '') + { + $count = \count($array); + + if ($count < $min || $count > $max) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', + $count, + $min, + $max + )); + } + } + + /** + * @psalm-pure + * @psalm-assert list $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isList($array, $message = '') + { + if (!\is_array($array)) { + static::reportInvalidArgument( + $message ?: 'Expected list - non-associative array.' + ); + } + + if ($array === \array_values($array)) { + return; + } + + $nextKey = -1; + foreach ($array as $k => $v) { + if ($k !== ++$nextKey) { + static::reportInvalidArgument( + $message ?: 'Expected list - non-associative array.' + ); + } + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-list $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isNonEmptyList($array, $message = '') + { + static::isList($array, $message); + static::notEmpty($array, $message); + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array $array + * @psalm-assert array $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isMap($array, $message = '') + { + if ( + !\is_array($array) || + \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') + ) { + static::reportInvalidArgument( + $message ?: 'Expected map - associative array with string keys.' + ); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array $array + * @psalm-assert array $array + * @psalm-assert !empty $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isNonEmptyMap($array, $message = '') + { + static::isMap($array, $message); + static::notEmpty($array, $message); + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function uuid($value, $message = '') + { + $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); + + // The nil UUID is special form of UUID that is specified to have all + // 128 bits set to zero. + if ('00000000-0000-0000-0000-000000000000' === $value) { + return; + } + + if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Value %s is not a valid UUID.', + static::valueToString($value) + )); + } + } + + /** + * @psalm-param class-string $class + * + * @param Closure $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function throws(Closure $expression, $class = 'Exception', $message = '') + { + static::string($class); + + $actual = 'none'; + + try { + $expression(); + } catch (Exception $e) { + $actual = \get_class($e); + if ($e instanceof $class) { + return; + } + } catch (Throwable $e) { + $actual = \get_class($e); + if ($e instanceof $class) { + return; + } + } + + static::reportInvalidArgument($message ?: \sprintf( + 'Expected to throw "%s", got "%s"', + $class, + $actual + )); + } + + /** + * @throws BadMethodCallException + */ + public static function __callStatic($name, $arguments) + { + if ('nullOr' === \substr($name, 0, 6)) { + if (null !== $arguments[0]) { + $method = \lcfirst(\substr($name, 6)); + \call_user_func_array(array(static::class, $method), $arguments); + } + + return; + } + + if ('all' === \substr($name, 0, 3)) { + static::isIterable($arguments[0]); + + $method = \lcfirst(\substr($name, 3)); + $args = $arguments; + + foreach ($arguments[0] as $entry) { + $args[0] = $entry; + + \call_user_func_array(array(static::class, $method), $args); + } + + return; + } + + throw new BadMethodCallException('No such method: '.$name); + } + + /** + * @param mixed $value + * + * @return string + */ + protected static function valueToString($value) + { + if (null === $value) { + return 'null'; + } + + if (true === $value) { + return 'true'; + } + + if (false === $value) { + return 'false'; + } + + if (\is_array($value)) { + return 'array'; + } + + if (\is_object($value)) { + if (\method_exists($value, '__toString')) { + return \get_class($value).': '.self::valueToString($value->__toString()); + } + + if ($value instanceof DateTime || $value instanceof DateTimeImmutable) { + return \get_class($value).': '.self::valueToString($value->format('c')); + } + + return \get_class($value); + } + + if (\is_resource($value)) { + return 'resource'; + } + + if (\is_string($value)) { + return '"'.$value.'"'; + } + + return (string) $value; + } + + /** + * @param mixed $value + * + * @return string + */ + protected static function typeToString($value) + { + return \is_object($value) ? \get_class($value) : \gettype($value); + } + + protected static function strlen($value) + { + if (!\function_exists('mb_detect_encoding')) { + return \strlen($value); + } + + if (false === $encoding = \mb_detect_encoding($value)) { + return \strlen($value); + } + + return \mb_strlen($value, $encoding); + } + + /** + * @param string $message + * + * @throws InvalidArgumentException + * + * @psalm-pure this method is not supposed to perform side-effects + * @psalm-return never + */ + protected static function reportInvalidArgument($message) + { + throw new InvalidArgumentException($message); + } + + private function __construct() + { + } +} diff --git a/cacme/vendor/webmozart/assert/src/InvalidArgumentException.php b/cacme/vendor/webmozart/assert/src/InvalidArgumentException.php new file mode 100644 index 0000000..9d95a58 --- /dev/null +++ b/cacme/vendor/webmozart/assert/src/InvalidArgumentException.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 Webmozart\Assert; + +class InvalidArgumentException extends \InvalidArgumentException +{ +} diff --git a/cacme/vendor/webmozart/assert/src/Mixin.php b/cacme/vendor/webmozart/assert/src/Mixin.php new file mode 100644 index 0000000..0f0a75e --- /dev/null +++ b/cacme/vendor/webmozart/assert/src/Mixin.php @@ -0,0 +1,5089 @@ + $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allString($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::string($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrString($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::string($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrStringNotEmpty($value, $message = '') + { + null === $value || static::stringNotEmpty($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allStringNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::stringNotEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrStringNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::stringNotEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert int|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrInteger($value, $message = '') + { + null === $value || static::integer($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::integer($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::integer($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert numeric|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIntegerish($value, $message = '') + { + null === $value || static::integerish($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIntegerish($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::integerish($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIntegerish($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::integerish($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert positive-int|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrPositiveInteger($value, $message = '') + { + null === $value || static::positiveInteger($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allPositiveInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::positiveInteger($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrPositiveInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::positiveInteger($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert float|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFloat($value, $message = '') + { + null === $value || static::float($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFloat($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::float($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFloat($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::float($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert numeric|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNumeric($value, $message = '') + { + null === $value || static::numeric($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNumeric($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::numeric($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNumeric($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::numeric($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert positive-int|0|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNatural($value, $message = '') + { + null === $value || static::natural($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNatural($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::natural($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNatural($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::natural($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert bool|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrBoolean($value, $message = '') + { + null === $value || static::boolean($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allBoolean($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::boolean($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrBoolean($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::boolean($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert scalar|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrScalar($value, $message = '') + { + null === $value || static::scalar($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allScalar($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::scalar($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrScalar($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::scalar($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert object|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrObject($value, $message = '') + { + null === $value || static::object($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allObject($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::object($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrObject($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::object($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert resource|null $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrResource($value, $type = null, $message = '') + { + null === $value || static::resource($value, $type, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allResource($value, $type = null, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::resource($entry, $type, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrResource($value, $type = null, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::resource($entry, $type, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert callable|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsCallable($value, $message = '') + { + null === $value || static::isCallable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsCallable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isCallable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsCallable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isCallable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert array|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsArray($value, $message = '') + { + null === $value || static::isArray($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsArray($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isArray($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsArray($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isArray($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable|null $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsTraversable($value, $message = '') + { + null === $value || static::isTraversable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsTraversable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isTraversable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsTraversable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isTraversable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert array|ArrayAccess|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsArrayAccessible($value, $message = '') + { + null === $value || static::isArrayAccessible($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsArrayAccessible($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isArrayAccessible($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsArrayAccessible($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isArrayAccessible($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert countable|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsCountable($value, $message = '') + { + null === $value || static::isCountable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsCountable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isCountable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsCountable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isCountable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsIterable($value, $message = '') + { + null === $value || static::isIterable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsIterable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isIterable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsIterable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isIterable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert ExpectedType|null $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsInstanceOf($value, $class, $message = '') + { + null === $value || static::isInstanceOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotInstanceOf($value, $class, $message = '') + { + null === $value || static::notInstanceOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param mixed $value + * @param array $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsInstanceOfAny($value, $classes, $message = '') + { + null === $value || static::isInstanceOfAny($value, $classes, $message); + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param mixed $value + * @param array $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsInstanceOfAny($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isInstanceOfAny($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param mixed $value + * @param array $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsInstanceOfAny($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isInstanceOfAny($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert ExpectedType|class-string|null $value + * + * @param object|string|null $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsAOf($value, $class, $message = '') + { + null === $value || static::isAOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable> $value + * + * @param iterable $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsAOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isAOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable|null> $value + * + * @param iterable $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsAOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isAOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string $class + * + * @param object|string|null $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsNotA($value, $class, $message = '') + { + null === $value || static::isNotA($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string $class + * + * @param iterable $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsNotA($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isNotA($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable $value + * @psalm-assert iterable|null> $value + * + * @param iterable $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsNotA($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isNotA($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param object|string|null $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsAnyOf($value, $classes, $message = '') + { + null === $value || static::isAnyOf($value, $classes, $message); + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param iterable $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsAnyOf($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isAnyOf($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array $classes + * + * @param iterable $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsAnyOf($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isAnyOf($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert empty $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsEmpty($value, $message = '') + { + null === $value || static::isEmpty($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotEmpty($value, $message = '') + { + null === $value || static::notEmpty($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNull($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::null($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotNull($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notNull($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert true|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrTrue($value, $message = '') + { + null === $value || static::true($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allTrue($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::true($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrTrue($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::true($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert false|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFalse($value, $message = '') + { + null === $value || static::false($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::false($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::false($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotFalse($value, $message = '') + { + null === $value || static::notFalse($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notFalse($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notFalse($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIp($value, $message = '') + { + null === $value || static::ip($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIp($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::ip($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIp($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::ip($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIpv4($value, $message = '') + { + null === $value || static::ipv4($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIpv4($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::ipv4($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIpv4($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::ipv4($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIpv6($value, $message = '') + { + null === $value || static::ipv6($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIpv6($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::ipv6($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIpv6($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::ipv6($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrEmail($value, $message = '') + { + null === $value || static::email($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allEmail($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::email($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrEmail($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::email($entry, $message); + } + } + + /** + * @param array|null $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUniqueValues($values, $message = '') + { + null === $values || static::uniqueValues($values, $message); + } + + /** + * @param iterable $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUniqueValues($values, $message = '') + { + static::isIterable($values); + + foreach ($values as $entry) { + static::uniqueValues($entry, $message); + } + } + + /** + * @param iterable $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUniqueValues($values, $message = '') + { + static::isIterable($values); + + foreach ($values as $entry) { + null === $entry || static::uniqueValues($entry, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrEq($value, $expect, $message = '') + { + null === $value || static::eq($value, $expect, $message); + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::eq($entry, $expect, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::eq($entry, $expect, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotEq($value, $expect, $message = '') + { + null === $value || static::notEq($value, $expect, $message); + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notEq($entry, $expect, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notEq($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrSame($value, $expect, $message = '') + { + null === $value || static::same($value, $expect, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::same($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::same($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotSame($value, $expect, $message = '') + { + null === $value || static::notSame($value, $expect, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notSame($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notSame($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrGreaterThan($value, $limit, $message = '') + { + null === $value || static::greaterThan($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allGreaterThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::greaterThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrGreaterThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::greaterThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrGreaterThanEq($value, $limit, $message = '') + { + null === $value || static::greaterThanEq($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allGreaterThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::greaterThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrGreaterThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::greaterThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLessThan($value, $limit, $message = '') + { + null === $value || static::lessThan($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLessThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lessThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLessThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lessThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLessThanEq($value, $limit, $message = '') + { + null === $value || static::lessThanEq($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLessThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lessThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLessThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lessThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrRange($value, $min, $max, $message = '') + { + null === $value || static::range($value, $min, $max, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allRange($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::range($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrRange($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::range($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrOneOf($value, $values, $message = '') + { + null === $value || static::oneOf($value, $values, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allOneOf($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::oneOf($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrOneOf($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::oneOf($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrInArray($value, $values, $message = '') + { + null === $value || static::inArray($value, $values, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allInArray($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::inArray($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrInArray($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::inArray($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrContains($value, $subString, $message = '') + { + null === $value || static::contains($value, $subString, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::contains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::contains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotContains($value, $subString, $message = '') + { + null === $value || static::notContains($value, $subString, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notContains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notContains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotWhitespaceOnly($value, $message = '') + { + null === $value || static::notWhitespaceOnly($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotWhitespaceOnly($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notWhitespaceOnly($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotWhitespaceOnly($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notWhitespaceOnly($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrStartsWith($value, $prefix, $message = '') + { + null === $value || static::startsWith($value, $prefix, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::startsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::startsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotStartsWith($value, $prefix, $message = '') + { + null === $value || static::notStartsWith($value, $prefix, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notStartsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notStartsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrStartsWithLetter($value, $message = '') + { + null === $value || static::startsWithLetter($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allStartsWithLetter($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::startsWithLetter($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrStartsWithLetter($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::startsWithLetter($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrEndsWith($value, $suffix, $message = '') + { + null === $value || static::endsWith($value, $suffix, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::endsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::endsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotEndsWith($value, $suffix, $message = '') + { + null === $value || static::notEndsWith($value, $suffix, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notEndsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notEndsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrRegex($value, $pattern, $message = '') + { + null === $value || static::regex($value, $pattern, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::regex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::regex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotRegex($value, $pattern, $message = '') + { + null === $value || static::notRegex($value, $pattern, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notRegex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notRegex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUnicodeLetters($value, $message = '') + { + null === $value || static::unicodeLetters($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUnicodeLetters($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::unicodeLetters($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUnicodeLetters($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::unicodeLetters($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrAlpha($value, $message = '') + { + null === $value || static::alpha($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allAlpha($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::alpha($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrAlpha($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::alpha($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrDigits($value, $message = '') + { + null === $value || static::digits($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allDigits($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::digits($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrDigits($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::digits($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrAlnum($value, $message = '') + { + null === $value || static::alnum($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allAlnum($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::alnum($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrAlnum($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::alnum($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert lowercase-string|null $value + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLower($value, $message = '') + { + null === $value || static::lower($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLower($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lower($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLower($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lower($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUpper($value, $message = '') + { + null === $value || static::upper($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUpper($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::upper($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUpper($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::upper($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLength($value, $length, $message = '') + { + null === $value || static::length($value, $length, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLength($value, $length, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::length($entry, $length, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLength($value, $length, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::length($entry, $length, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMinLength($value, $min, $message = '') + { + null === $value || static::minLength($value, $min, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMinLength($value, $min, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::minLength($entry, $min, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMinLength($value, $min, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::minLength($entry, $min, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMaxLength($value, $max, $message = '') + { + null === $value || static::maxLength($value, $max, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMaxLength($value, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::maxLength($entry, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMaxLength($value, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::maxLength($entry, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLengthBetween($value, $min, $max, $message = '') + { + null === $value || static::lengthBetween($value, $min, $max, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLengthBetween($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lengthBetween($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLengthBetween($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lengthBetween($entry, $min, $max, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFileExists($value, $message = '') + { + null === $value || static::fileExists($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFileExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::fileExists($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFileExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::fileExists($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFile($value, $message = '') + { + null === $value || static::file($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFile($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::file($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFile($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::file($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrDirectory($value, $message = '') + { + null === $value || static::directory($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allDirectory($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::directory($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrDirectory($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::directory($entry, $message); + } + } + + /** + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrReadable($value, $message = '') + { + null === $value || static::readable($value, $message); + } + + /** + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allReadable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::readable($entry, $message); + } + } + + /** + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrReadable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::readable($entry, $message); + } + } + + /** + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrWritable($value, $message = '') + { + null === $value || static::writable($value, $message); + } + + /** + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allWritable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::writable($entry, $message); + } + } + + /** + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrWritable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::writable($entry, $message); + } + } + + /** + * @psalm-assert class-string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrClassExists($value, $message = '') + { + null === $value || static::classExists($value, $message); + } + + /** + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allClassExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::classExists($entry, $message); + } + } + + /** + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrClassExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::classExists($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert class-string|ExpectedType|null $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrSubclassOf($value, $class, $message = '') + { + null === $value || static::subclassOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable|ExpectedType> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allSubclassOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::subclassOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $class + * @psalm-assert iterable|ExpectedType|null> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrSubclassOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::subclassOf($entry, $class, $message); + } + } + + /** + * @psalm-assert class-string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrInterfaceExists($value, $message = '') + { + null === $value || static::interfaceExists($value, $message); + } + + /** + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allInterfaceExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::interfaceExists($entry, $message); + } + } + + /** + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrInterfaceExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::interfaceExists($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $interface + * @psalm-assert class-string|null $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrImplementsInterface($value, $interface, $message = '') + { + null === $value || static::implementsInterface($value, $interface, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $interface + * @psalm-assert iterable> $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allImplementsInterface($value, $interface, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::implementsInterface($entry, $interface, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string $interface + * @psalm-assert iterable|null> $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrImplementsInterface($value, $interface, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::implementsInterface($entry, $interface, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrPropertyExists($classOrObject, $property, $message = '') + { + null === $classOrObject || static::propertyExists($classOrObject, $property, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allPropertyExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::propertyExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrPropertyExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::propertyExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrPropertyNotExists($classOrObject, $property, $message = '') + { + null === $classOrObject || static::propertyNotExists($classOrObject, $property, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allPropertyNotExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::propertyNotExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrPropertyNotExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::propertyNotExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMethodExists($classOrObject, $method, $message = '') + { + null === $classOrObject || static::methodExists($classOrObject, $method, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMethodExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::methodExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMethodExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::methodExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMethodNotExists($classOrObject, $method, $message = '') + { + null === $classOrObject || static::methodNotExists($classOrObject, $method, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMethodNotExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::methodNotExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable $classOrObject + * + * @param iterable $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMethodNotExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::methodNotExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * + * @param array|null $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrKeyExists($array, $key, $message = '') + { + null === $array || static::keyExists($array, $key, $message); + } + + /** + * @psalm-pure + * + * @param iterable $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allKeyExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::keyExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrKeyExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::keyExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * + * @param array|null $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrKeyNotExists($array, $key, $message = '') + { + null === $array || static::keyNotExists($array, $key, $message); + } + + /** + * @psalm-pure + * + * @param iterable $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allKeyNotExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::keyNotExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrKeyNotExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::keyNotExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert array-key|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrValidArrayKey($value, $message = '') + { + null === $value || static::validArrayKey($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allValidArrayKey($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::validArrayKey($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrValidArrayKey($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::validArrayKey($entry, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrCount($array, $number, $message = '') + { + null === $array || static::count($array, $number, $message); + } + + /** + * @param iterable $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allCount($array, $number, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::count($entry, $number, $message); + } + } + + /** + * @param iterable $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrCount($array, $number, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::count($entry, $number, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMinCount($array, $min, $message = '') + { + null === $array || static::minCount($array, $min, $message); + } + + /** + * @param iterable $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMinCount($array, $min, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::minCount($entry, $min, $message); + } + } + + /** + * @param iterable $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMinCount($array, $min, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::minCount($entry, $min, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMaxCount($array, $max, $message = '') + { + null === $array || static::maxCount($array, $max, $message); + } + + /** + * @param iterable $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMaxCount($array, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::maxCount($entry, $max, $message); + } + } + + /** + * @param iterable $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMaxCount($array, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::maxCount($entry, $max, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrCountBetween($array, $min, $max, $message = '') + { + null === $array || static::countBetween($array, $min, $max, $message); + } + + /** + * @param iterable $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allCountBetween($array, $min, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::countBetween($entry, $min, $max, $message); + } + } + + /** + * @param iterable $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrCountBetween($array, $min, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::countBetween($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert list|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsList($array, $message = '') + { + null === $array || static::isList($array, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-list|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsNonEmptyList($array, $message = '') + { + null === $array || static::isNonEmptyList($array, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsNonEmptyList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isNonEmptyList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsNonEmptyList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isNonEmptyList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array|null $array + * @psalm-assert array|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsMap($array, $message = '') + { + null === $array || static::isMap($array, $message); + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable> $array + * @psalm-assert iterable> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isMap($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable|null> $array + * @psalm-assert iterable|null> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isMap($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsNonEmptyMap($array, $message = '') + { + null === $array || static::isNonEmptyMap($array, $message); + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsNonEmptyMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isNonEmptyMap($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable|null> $array + * @psalm-assert iterable|null> $array + * @psalm-assert iterable $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsNonEmptyMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isNonEmptyMap($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUuid($value, $message = '') + { + null === $value || static::uuid($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUuid($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::uuid($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUuid($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::uuid($entry, $message); + } + } + + /** + * @psalm-param class-string $class + * + * @param Closure|null $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrThrows($expression, $class = 'Exception', $message = '') + { + null === $expression || static::throws($expression, $class, $message); + } + + /** + * @psalm-param class-string $class + * + * @param iterable $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allThrows($expression, $class = 'Exception', $message = '') + { + static::isIterable($expression); + + foreach ($expression as $entry) { + static::throws($entry, $class, $message); + } + } + + /** + * @psalm-param class-string $class + * + * @param iterable $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrThrows($expression, $class = 'Exception', $message = '') + { + static::isIterable($expression); + + foreach ($expression as $entry) { + null === $entry || static::throws($entry, $class, $message); + } + } +} diff --git a/cacme/vendor/workerman/validation/CHANGELOG.md b/cacme/vendor/workerman/validation/CHANGELOG.md new file mode 100644 index 0000000..9d082d4 --- /dev/null +++ b/cacme/vendor/workerman/validation/CHANGELOG.md @@ -0,0 +1,161 @@ +# Changes in Respect\Validation 2.x + +## 2.3 + +Versioning Changes: + + - Dropped support for PHP 7.4. + - Updated dev dependencies + +Deprecations: + + - Symfony façade validators are no longer supported and were + removed. + +Fixes: + + - `KeySet` now reports which extra keys are causing the rule to fail. + +Changes: + + - You can no longer wrap `KeySet` in `Not`. + - `Phone` now uses `giggsey/libphonenumber-for-php`, this package needs + to be installed if you want to use this validator. + - `Phone` now supports the parameter `$countryCode` to validate phones + of a specific country. + +## 2.2.4 + +Meta: + + - CHANGELOG.md is being written once again to provide an overview + of active changes to the API and codebase. + +Versioning Changes: + + - Dropped PHP 7.3 support. + - Added support for PHP 8.0 and PHP 8.1. This will be the + last release with PHP 7.4 support. Support for PHP 8.2 is considered + experimental, local development should be done at 8.1. + +Deprecations: + + - Zend Framework façade validators are no longer supported and were + removed. + - Symfony façade validators are no longer suggested, and will be + removed in release 2.3. + - v::dateTime('z') is not supported anymore in PHP8, and should not be relied upon + +Fixes: + - Updated bin/update-currency-codes to fetch XML from another source. + - Updated bin/update-iso-codes to new file format. + - Updated regionals (CountryCode.php, CurrencyCode.php, Tld.php) (2023-02-13). + - Added RuPay card validation (thanks @rakshit087) + - Fixed `v::decimal()` for float values (thanks @scruwi) + - Added `v::portugueseNif()` to validate _Número de Identificação Fiscal_ in Portugal (thanks @goncalo-andrade). + - Allow 5-digit and 6-digit postal codes for Cambodia (thanks @omega3000) + - `v::intval()` now handles negative values with trailing zeroes better (thanks @l-x) + +## 2.2.x + +Changelogs between 1.1.0 and 2.2.4 are available only through `git log` and GitHub Releases. + +# Changes in Respect\Validation 1.x + +All notable changes of the Respect\Validation releases are documented in this file. + +## 1.1.0 - 2016-04-24 + +### Added + +- Create "Fibonacci" rule (#637) +- Create "IdentityCard" rule (#632) +- Create "Image" rule (#621) +- Create "LanguageCode" rule (#597) +- Create "Pesel" rule (#616) +- Create "PhpLabel" rule (#652) + +### Changed + +- Allow the define brands for credit card validation (#661) +- Define names for the child of Not rule (#641) +- Ensure namespace separator on appended prefixes (#666) +- Length gets length of integers (#643) +- Set template for the only rule in the chain (#663) +- Throw an exception when age is not an integer (#667) +- Use "{less/greater} than or equal to" phrasing (#604) + +## 1.0.0 - 2015-10-24 + +### Added + +- Add "alpha-3" and "numeric" formats for "CountryCode" rule (#530) +- Add support for PHP 7 (#426) +- Create "BoolVal" rule (#583) +- Create "Bsn" rule (#450) +- Create "CallableType" rule (#397) +- Create "Countable" rule (#566) +- Create "CurrencyCode" rule (#567) +- Create "Extension" rule (#360) +- Create "Factor" rule (#405) +- Create "Finite" rule (#397) +- Create "FloatType" rule (#565) +- Create "Identical" rule (#442) +- Create "Imei" rule (#590) +- Create "Infinite" rule (#397) +- Create "IntType" rule (#451) +- Create "Iterable" rule (#570) +- Create "KeyNested" rule (#429) +- Create "KeySet" rule (#374) +- Create "KeyValue" rule (#441) +- Create "Mimetype" rule (#361) +- Create "NotBlank" rule (#443) +- Create "NotOptional" rule (#448) +- Create "Optional" rule (#423) +- Create "ResourceType" rule (#397) +- Create "ScalarVal" rule (#397) +- Create "Size" rule (#359) +- Create "SubdivisionCode" rule for 252 countries (#411) +- Create "VideoUrl" rule (#410) +- Create method `getMessages()` for nested exceptions (#406) + +### Changed + +- Add country code to the message of "PostalCode" exception rule (#413) +- Make "ArrayVal" validate only if the input can be used as an array (#574) +- Make "Between" rule inclusive (#445) +- Make "Max" rule inclusive (#445) +- Make "Min" rule inclusive (#445) +- New generic top-level domains (#368) +- On `AbstractRelated` (`Attribute`, `Call` and `Key`) define names for child rules (#365) +- On exceptions, convert `Array` to string (#387) +- On exceptions, convert `Exception` to string (#399) +- On exceptions, convert `Traversable` to string (#399) +- On exceptions, convert resources to string (#399) +- On exceptions, do not display parent message then rule has only one child (#407) +- On exceptions, improve `Object` conversion to string (#399) +- On exceptions, improve conversion of all values by using JSON (#399) +- On exceptions, nested messages are displayed in a Markdown list (#588) +- Rename exception class "AbstractGroupedException" to "GroupedValidationException" (#591) +- Rename exception class "AbstractNestedException" to "NestedValidationException" (#591) +- Rename rule "Arr" to "ArrayVal" +- Rename rule "Bool" to "BoolType" (#426) +- Rename rule "False" to "FalseVal" (#426) +- Rename rule "Float" to "FloatVal" (#426) +- Rename rule "Int" to "IntVal" (#426) +- Rename rule "NullValue" to "NullType" +- Rename rule "Object" to "ObjectType" +- Rename rule "String" to "StringType" (#426) +- Rename rule "True" to "TrueVal" (#426) +- Use `filter_var()` on "TrueVal" and "FalseVal" rules (#409) + +### Removed + +- Drop support for PHP 5.3 (#466) +- Remove `addOr()` shortcut (#444) +- Remove `NestedValidationExceptionInterface` interface (#591) +- Remove `not()` shortcut (#444) +- Remove `ValidationExceptionInterface` interface (#591) +- Remove identical checking from "Equals" rule (#442) +- Removed Deprecated Rules (#277) +- Validation rules do not accept an empty string by default (#422) diff --git a/cacme/vendor/workerman/validation/CONTRIBUTING.md b/cacme/vendor/workerman/validation/CONTRIBUTING.md new file mode 100644 index 0000000..a760063 --- /dev/null +++ b/cacme/vendor/workerman/validation/CONTRIBUTING.md @@ -0,0 +1,244 @@ +# Contributing + +Contributions to Respect\Validation are always welcome. You make our lives +easier by sending us your contributions through [pull requests][]. + +Pull requests for bug fixes must be based on the oldest stable version's branch +whereas pull requests for new features must be based on the `master` branch. + +Due to time constraints, we are not always able to respond as quickly as we +would like. Please do not take delays personal and feel free to remind us here, +on IRC, or on Gitter if you feel that we forgot to respond. + +Please see the [project documentation][] before proceeding. You should also know +about [PHP-FIG][]'s standards and basic unit testing, but we're sure you can +learn that just by looking at other rules. Pick the simple ones like `ArrayType` +to begin. + +Before writing anything, feature or bug fix: +- Check if there is already an issue related to it (opened or closed) and if + someone is already working on that; + - If there is not, [open an issue][] and notify everybody that you're going + to work on that; + - If there is, create a comment to notify everybody that you're going to + work on that. +- Make sure that what you need is not done yet + +## Adding a new validator + +A common validator (rule) on Respect\Validation is composed of three classes: + + * `library/Rules/YourRuleName.php`: the rule itself + * `library/Exceptions/YourRuleNameException.php`: the exception thrown by the rule + * `tests/unit/Rules/YourRuleNameTest.php`: tests for the rule + +The classes are pretty straightforward. In the sample below, we're going to +create a validator that validates if a string is equal to "Hello World". + +- Classes should be `final` unless they are used in a different scope; +- Properties should be `private` unless they are used in a different scope; +- Classes should use strict typing; +- Some docblocks are required. + +### Creating the rule + +The rule itself needs to implement the `Validatable` interface but, it is +convenient to just extend the `AbstractRule` class. +Doing that, you'll only need to declare one method: `validate($input)`. +This method must return `true` or `false`. + +If your validator class is `HelloWorld`, it will be available as `v::helloWorld()` +and will natively have support for chaining and everything else. + +```php + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Explain in one sentence what this rule does. + * + * @author Your Name + */ +final class HelloWorld extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $input === 'Hello World'; + } +} +``` + +### Creating the rule exception + +Just that and we're done with the rule code. The Exception requires you to +declare messages used by `assert()` and `check()`. Messages are declared in +affirmative and negative moods, so if anyone calls `v::not(v::helloWorld())` the +library will show the appropriate message. + +```php + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Your Name + */ +final class HelloWorldException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} must be a Hello World', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} must not be a Hello World', + ] + ]; +} +``` + +### Creating unit tests + +Finally, we need to test if everything is running smooth. We have `RuleTestCase` +that allows us to make easier to test rules, but you fell free to use the +`PHPUnit\Framework\TestCase` if you want or you need it's necessary. + +The `RuleTestCase` extends PHPUnit's `PHPUnit\Framework\TestCase` class, so you +are able to use any methods of it. By extending `RuleTestCase` you should +implement two methods that should return a [data provider][] with the rule as +first item of the arrays: + +- `providerForValidInput`: Will test when `validate()` should return `true` +- `providerForInvalidInput`: Will test when `validate()` should return `false` + +```php + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Test\RuleTestCase; + +/** + * @group rule + * + * @covers \Respect\Validation\Rules\HelloWorld + * + * @author Your Name + */ +final class HelloWorldTest extends RuleTestCase +{ + /** + * {@inheritDoc} + */ + public static function providerForValidInput(): array + { + $rule = new HelloWorld(); + + return [ + [$rule, 'Hello World'], + ]; + } + + /** + * {@inheritDoc} + */ + public static function providerForInvalidInput(): array + { + $rule = new HelloWorld(); + + return [ + [$rule, 'Not a hello'], + [$rule, 'Hello darkness, my old friend'], + [$rule, 'Hello is it me you\'re looking for?'], + ]; + } +} +``` + +If the constructor of your rule accepts arguments you may create specific tests +for it other than what is covered by `RuleTestCase`. + +### Helping us a little bit more + +You rule will be accepted only with these 3 files (rule, exception and unit test), +but if you really want to help us, you can follow the example of [ArrayType][] by: + +- Adding your new rule on the `Validator`'s class docblock; +- Writing a documentation for your new rule; +- Creating integration tests with PHPT. + +As we already said, none of them are required but you will help us a lot. + +## Documentation + +Our docs at https://respect-validation.readthedocs.io are generated from our +Markdown files. Add your brand new rule and it should be soon available. + +## Running Tests + +After run `composer install` on the library's root directory you must run PHPUnit. + +### Linux + +You can test the project using the commands: +```sh +$ vendor/bin/phpunit +``` + +or + +```sh +$ composer phpunit +``` + +### Windows + +You can test the project using the commands: +```sh +> vendor\bin\phpunit +``` + +or + +```sh +> composer phpunit +``` + +No test should fail. + +You can tweak the PHPUnit's settings by copying `phpunit.xml.dist` to `phpunit.xml` +and changing it according to your needs. + +[ArrayType]: https://github.com/Respect/Validation/commit/f08a1fa +[data provider]: https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers "PHPUnit Data Providers" +[open an issue]: http://github.com/Respect/Validation/issues +[PHP-FIG]: http://www.php-fig.org "PHP Framework Interop Group" +[project documentation]: https://respect-validation.readthedocs.io/ "Respect\Validation documentation" +[pull requests]: http://help.github.com/pull-requests "GitHub pull requests" diff --git a/cacme/vendor/workerman/validation/LICENSE b/cacme/vendor/workerman/validation/LICENSE new file mode 100644 index 0000000..1b92eaf --- /dev/null +++ b/cacme/vendor/workerman/validation/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Alexandre Gomes Gaigalas + +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/cacme/vendor/workerman/validation/README.md b/cacme/vendor/workerman/validation/README.md new file mode 100644 index 0000000..b81b4a1 --- /dev/null +++ b/cacme/vendor/workerman/validation/README.md @@ -0,0 +1,20 @@ +# [Respect\Validation 验证器](https://github.com/Respect/Validation) 汉化版 +# Respect\Validation + +[![Build Status](https://img.shields.io/github/actions/workflow/status/Respect/Validation/continuous-integration.yml?branch=master&style=flat-square)](https://github.com/Respect/Validation/actions/workflows/continuous-integration.yml) +[![Code Coverage](https://img.shields.io/codecov/c/github/Respect/Validation?style=flat-square)](https://codecov.io/gh/Respect/Validation) +[![Latest Stable Version](https://img.shields.io/packagist/v/respect/validation.svg?style=flat-square)](https://packagist.org/packages/respect/validation) +[![Total Downloads](https://img.shields.io/packagist/dt/respect/validation.svg?style=flat-square)](https://packagist.org/packages/respect/validation) +[![License](https://img.shields.io/packagist/l/respect/validation.svg?style=flat-square)](https://packagist.org/packages/respect/validation) + +The most awesome validation engine ever created for PHP. + +- Complex rules made simple: `v::numericVal()->positive()->between(1, 255)->validate($input)`. +- [Granularity control](docs/feature-guide.md#validation-methods) for advanced reporting. +- [More than 150](docs/list-of-rules.md) (fully tested) validation rules. +- [A concrete API](docs/concrete-api.md) for non fluent usage. + +Learn More: + +* [Documentation](https://respect-validation.readthedocs.io) +* [How to contribute](CONTRIBUTING.md) diff --git a/cacme/vendor/workerman/validation/composer.json b/cacme/vendor/workerman/validation/composer.json new file mode 100644 index 0000000..c89f527 --- /dev/null +++ b/cacme/vendor/workerman/validation/composer.json @@ -0,0 +1,73 @@ +{ + "name": "workerman/validation", + "description": "The most awesome validation engine ever created for PHP. Respect/Validation 汉化版本", + "keywords": ["respect", "validation", "validator"], + "type": "library", + "homepage": "http://respect.github.io/Validation/", + "license": "MIT", + "authors": [ + { + "name": "Respect/Validation Contributors", + "homepage": "https://github.com/Respect/Validation/graphs/contributors" + } + ], + "config": { + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "require": { + "php": "^8.0 || ^8.1 || ^8.2", + "respect/stringifier": "^0.2.0", + "symfony/polyfill-mbstring": "^1.2" + }, + "require-dev": { + "egulias/email-validator": "^3.0", + "giggsey/libphonenumber-for-php-lite": "^8.13", + "malukenho/docheader": "^1.0", + "mikey179/vfsstream": "^1.6", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.6", + "psr/http-message": "^1.0", + "respect/coding-standard": "^3.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "suggest": { + "ext-bcmath": "Arbitrary Precision Mathematics", + "ext-fileinfo": "File Information", + "ext-mbstring": "Multibyte String Functions", + "egulias/email-validator": "Improves the Email rule if available", + "giggsey/libphonenumber-for-php-lite": "Enables the phone rule if available" + }, + "autoload": { + "psr-4": { + "Respect\\Validation\\": "library/" + } + }, + "autoload-dev": { + "psr-4": { + "Respect\\Validation\\": "tests/unit/", + "Respect\\Validation\\Test\\": "tests/library/" + }, + "files": [ + "tests/integration/lib/helpers.php" + ] + }, + "scripts": { + "docheader": "vendor/bin/docheader check library/ tests/", + "phpcs": "vendor/bin/phpcs", + "phpstan": "vendor/bin/phpstan analyze", + "phpunit": "vendor/bin/phpunit", + "phpunit-integration": "vendor/bin/phpunit --testsuite=integration", + "phpunit-unit": "vendor/bin/phpunit --testsuite=unit", + "qa": [ + "@docheader", + "@phpcs", + "@phpstan", + "@phpunit" + ] + } +} diff --git a/cacme/vendor/workerman/validation/data/domain/public-suffix/AC.php b/cacme/vendor/workerman/validation/data/domain/public-suffix/AC.php new file mode 100644 index 0000000..5b4fc8c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/domain/public-suffix/AC.php @@ -0,0 +1,11 @@ + "Andorra", + "subdivisions" => [ + "02" => "Canillo", + "03" => "Encamp", + "04" => "La Massana", + "05" => "Ordino", + "06" => "Sant Julià de Lòria", + "07" => "Andorra la Vella", + "08" => "Escaldes-Engordany" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AE.php new file mode 100644 index 0000000..933d160 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AE.php @@ -0,0 +1,13 @@ + "United Arab Emirates", + "subdivisions" => [ + "AJ" => "‘Ajmān", + "AZ" => "Abū Z̧aby", + "DU" => "Dubayy", + "FU" => "Al Fujayrah", + "RK" => "Ra’s al Khaymah", + "SH" => "Ash Shāriqah", + "UQ" => "Umm al Qaywayn" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AF.php new file mode 100644 index 0000000..d33f2f5 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AF.php @@ -0,0 +1,40 @@ + "Afghanistan", + "subdivisions" => [ + "BAL" => "Balkh", + "BAM" => "Bāmyān", + "BDG" => "Bādghīs", + "BDS" => "Badakhshān", + "BGL" => "Baghlān", + "DAY" => "Dāykundī", + "FRA" => "Farāh", + "FYB" => "Fāryāb", + "GHA" => "Ghaznī", + "GHO" => "Ghōr", + "HEL" => "Helmand", + "HER" => "Herāt", + "JOW" => "Jowzjān", + "KAB" => "Kābul", + "KAN" => "Kandahār", + "KAP" => "Kāpīsā", + "KDZ" => "Kunduz", + "KHO" => "Khōst", + "KNR" => "Kunaṟ", + "LAG" => "Laghmān", + "LOG" => "Lōgar", + "NAN" => "Nangarhār", + "NIM" => "Nīmrōz", + "NUR" => "Nūristān", + "PAN" => "Panjshayr", + "PAR" => "Parwān", + "PIA" => "Paktiyā", + "PKA" => "Paktīkā", + "SAM" => "Samangān", + "SAR" => "Sar-e Pul", + "TAK" => "Takhār", + "URU" => "Uruzgān", + "WAR" => "Wardak", + "ZAB" => "Zābul" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AG.php new file mode 100644 index 0000000..6524330 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AG.php @@ -0,0 +1,14 @@ + "Antigua and Barbuda", + "subdivisions" => [ + "03" => "Saint George", + "04" => "Saint John", + "05" => "Saint Mary", + "06" => "Saint Paul", + "07" => "Saint Peter", + "08" => "Saint Philip", + "10" => "Barbuda", + "11" => "Redonda" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AI.php new file mode 100644 index 0000000..97d787e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AI.php @@ -0,0 +1,6 @@ + "Anguilla", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AL.php new file mode 100644 index 0000000..dfc6db5 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AL.php @@ -0,0 +1,18 @@ + "Albania", + "subdivisions" => [ + "01" => "Berat", + "02" => "Durrës", + "03" => "Elbasan", + "04" => "Fier", + "05" => "Gjirokastër", + "06" => "Korçë", + "07" => "Kukës", + "08" => "Lezhë", + "09" => "Dibër", + "10" => "Shkodër", + "11" => "Tiranë", + "12" => "Vlorë" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AM.php new file mode 100644 index 0000000..08e79d6 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AM.php @@ -0,0 +1,17 @@ + "Armenia", + "subdivisions" => [ + "AG" => "Aragac̣otn", + "AR" => "Ararat", + "AV" => "Armavir", + "ER" => "Erevan", + "GR" => "Geġark'unik'", + "KT" => "Kotayk'", + "LO" => "Loṙi", + "SH" => "Širak", + "SU" => "Syunik'", + "TV" => "Tavuš", + "VD" => "Vayoć Jor" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AO.php new file mode 100644 index 0000000..a57d8d1 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AO.php @@ -0,0 +1,24 @@ + "Angola", + "subdivisions" => [ + "BGO" => "Bengo", + "BGU" => "Benguela", + "BIE" => "Bié", + "CAB" => "Cabinda", + "CCU" => "Cuando Cubango", + "CNN" => "Cunene", + "CNO" => "Cuanza-Norte", + "CUS" => "Cuanza-Sul", + "HUA" => "Huambo", + "HUI" => "Huíla", + "LNO" => "Lunda-Norte", + "LSU" => "Lunda-Sul", + "LUA" => "Luanda", + "MAL" => "Malange", + "MOX" => "Moxico", + "NAM" => "Namibe", + "UIG" => "Uíge", + "ZAI" => "Zaire" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AQ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AQ.php new file mode 100644 index 0000000..bfca8b7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AQ.php @@ -0,0 +1,6 @@ + "Antarctica", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AR.php new file mode 100644 index 0000000..b10c5fe --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AR.php @@ -0,0 +1,30 @@ + "Argentina", + "subdivisions" => [ + "A" => "Salta", + "B" => "Buenos Aires", + "C" => "Ciudad Autónoma de Buenos Aires", + "D" => "San Luis", + "E" => "Entre Ríos", + "F" => "La Rioja", + "G" => "Santiago del Estero", + "H" => "Chaco", + "J" => "San Juan", + "K" => "Catamarca", + "L" => "La Pampa", + "M" => "Mendoza", + "N" => "Misiones", + "P" => "Formosa", + "Q" => "Neuquén", + "R" => "Río Negro", + "S" => "Santa Fe", + "T" => "Tucumán", + "U" => "Chubut", + "V" => "Tierra del Fuego", + "W" => "Corrientes", + "X" => "Córdoba", + "Y" => "Jujuy", + "Z" => "Santa Cruz" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AS.php new file mode 100644 index 0000000..2f1a65c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AS.php @@ -0,0 +1,6 @@ + "American Samoa", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AT.php new file mode 100644 index 0000000..6d62a19 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AT.php @@ -0,0 +1,15 @@ + "Austria", + "subdivisions" => [ + "1" => "Burgenland", + "2" => "Kärnten", + "3" => "Niederösterreich", + "4" => "Oberösterreich", + "5" => "Salzburg", + "6" => "Steiermark", + "7" => "Tirol", + "8" => "Vorarlberg", + "9" => "Wien" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AU.php new file mode 100644 index 0000000..2823163 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AU.php @@ -0,0 +1,14 @@ + "Australia", + "subdivisions" => [ + "ACT" => "Australian Capital Territory", + "NSW" => "New South Wales", + "NT" => "Northern Territory", + "QLD" => "Queensland", + "SA" => "South Australia", + "TAS" => "Tasmania", + "VIC" => "Victoria", + "WA" => "Western Australia" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AW.php new file mode 100644 index 0000000..86fe0ee --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AW.php @@ -0,0 +1,6 @@ + "Aruba", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AX.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AX.php new file mode 100644 index 0000000..85b0881 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AX.php @@ -0,0 +1,6 @@ + "Åland Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/AZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/AZ.php new file mode 100644 index 0000000..bdc2253 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/AZ.php @@ -0,0 +1,84 @@ + "Azerbaijan", + "subdivisions" => [ + "ABS" => "Abşeron", + "AGA" => "Ağstafa", + "AGC" => "Ağcabədi", + "AGM" => "Ağdam", + "AGS" => "Ağdaş", + "AGU" => "Ağsu", + "AST" => "Astara", + "BA" => "Bakı", + "BAB" => "Babək", + "BAL" => "Balakən", + "BAR" => "Bərdə", + "BEY" => "Beyləqan", + "BIL" => "Biləsuvar", + "CAB" => "Cəbrayıl", + "CAL" => "Cəlilabad", + "CUL" => "Culfa", + "DAS" => "Daşkəsən", + "FUZ" => "Füzuli", + "GA" => "Gəncə", + "GAD" => "Gədəbəy", + "GOR" => "Goranboy", + "GOY" => "Göyçay", + "GYG" => "Göygöl", + "HAC" => "Hacıqabul", + "IMI" => "İmişli", + "ISM" => "İsmayıllı", + "KAL" => "Kəlbəcər", + "KAN" => "Kǝngǝrli", + "KUR" => "Kürdəmir", + "LA" => "Lənkəran", + "LAC" => "Laçın", + "LAN" => "Lənkəran", + "LER" => "Lerik", + "MAS" => "Masallı", + "MI" => "Mingəçevir", + "NA" => "Naftalan", + "NEF" => "Neftçala", + "NV" => "Naxçıvan", + "NX" => "Naxçıvan", + "OGU" => "Oğuz", + "ORD" => "Ordubad", + "QAB" => "Qəbələ", + "QAX" => "Qax", + "QAZ" => "Qazax", + "QBA" => "Quba", + "QBI" => "Qubadlı", + "QOB" => "Qobustan", + "QUS" => "Qusar", + "SA" => "Şəki", + "SAB" => "Sabirabad", + "SAD" => "Sədərək", + "SAH" => "Şahbuz", + "SAK" => "Şəki", + "SAL" => "Salyan", + "SAR" => "Şərur", + "SAT" => "Saatlı", + "SBN" => "Şabran", + "SIY" => "Siyəzən", + "SKR" => "Şəmkir", + "SM" => "Sumqayıt", + "SMI" => "Şamaxı", + "SMX" => "Samux", + "SR" => "Şirvan", + "SUS" => "Şuşa", + "TAR" => "Tərtər", + "TOV" => "Tovuz", + "UCA" => "Ucar", + "XA" => "Xankəndi", + "XAC" => "Xaçmaz", + "XCI" => "Xocalı", + "XIZ" => "Xızı", + "XVD" => "Xocavənd", + "YAR" => "Yardımlı", + "YE" => "Yevlax", + "YEV" => "Yevlax", + "ZAN" => "Zəngilan", + "ZAQ" => "Zaqatala", + "ZAR" => "Zərdab" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BA.php new file mode 100644 index 0000000..082aa26 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BA.php @@ -0,0 +1,9 @@ + "Bosnia and Herzegovina", + "subdivisions" => [ + "BIH" => "Federacija Bosne i Hercegovine", + "BRC" => "Brčko distrikt", + "SRP" => "Republika Srpska" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BB.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BB.php new file mode 100644 index 0000000..0ef4a92 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BB.php @@ -0,0 +1,17 @@ + "Barbados", + "subdivisions" => [ + "01" => "Christ Church", + "02" => "Saint Andrew", + "03" => "Saint George", + "04" => "Saint James", + "05" => "Saint John", + "06" => "Saint Joseph", + "07" => "Saint Lucy", + "08" => "Saint Michael", + "09" => "Saint Peter", + "10" => "Saint Philip", + "11" => "Saint Thomas" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BD.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BD.php new file mode 100644 index 0000000..fe62cb2 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BD.php @@ -0,0 +1,78 @@ + "Bangladesh", + "subdivisions" => [ + "01" => "Bandarban", + "02" => "Barguna", + "03" => "Bogura", + "04" => "Brahmanbaria", + "05" => "Bagerhat", + "06" => "Barishal", + "07" => "Bhola", + "08" => "Cumilla", + "09" => "Chandpur", + "10" => "Chattogram", + "11" => "Cox's Bazar", + "12" => "Chuadanga", + "13" => "Dhaka", + "14" => "Dinajpur", + "15" => "Faridpur", + "16" => "Feni", + "17" => "Gopalganj", + "18" => "Gazipur", + "19" => "Gaibandha", + "20" => "Habiganj", + "21" => "Jamalpur", + "22" => "Jashore", + "23" => "Jhenaidah", + "24" => "Joypurhat", + "25" => "Jhalakathi", + "26" => "Kishoreganj", + "27" => "Khulna", + "28" => "Kurigram", + "29" => "Khagrachhari", + "30" => "Kushtia", + "31" => "Lakshmipur", + "32" => "Lalmonirhat", + "33" => "Manikganj", + "34" => "Mymensingh", + "35" => "Munshiganj", + "36" => "Madaripur", + "37" => "Magura", + "38" => "Moulvibazar", + "39" => "Meherpur", + "40" => "Narayanganj", + "41" => "Netrakona", + "42" => "Narsingdi", + "43" => "Narail", + "44" => "Natore", + "45" => "Chapai Nawabganj", + "46" => "Nilphamari", + "47" => "Noakhali", + "48" => "Naogaon", + "49" => "Pabna", + "50" => "Pirojpur", + "51" => "Patuakhali", + "52" => "Panchagarh", + "53" => "Rajbari", + "54" => "Rajshahi", + "55" => "Rangpur", + "56" => "Rangamati", + "57" => "Sherpur", + "58" => "Satkhira", + "59" => "Sirajganj", + "60" => "Sylhet", + "61" => "Sunamganj", + "62" => "Shariatpur", + "63" => "Tangail", + "64" => "Thakurgaon", + "A" => "Barishal", + "B" => "Chattogram", + "C" => "Dhaka", + "D" => "Khulna", + "E" => "Rajshahi", + "F" => "Rangpur", + "G" => "Sylhet", + "H" => "Mymensingh" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BE.php new file mode 100644 index 0000000..5ed5f81 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BE.php @@ -0,0 +1,19 @@ + "Belgium", + "subdivisions" => [ + "BRU" => "Brussels Hoofdstedelijk Gewest", + "VAN" => "Antwerpen", + "VBR" => "Vlaams-Brabant", + "VLG" => "Vlaams Gewest", + "VLI" => "Limburg", + "VOV" => "Oost-Vlaanderen", + "VWV" => "West-Vlaanderen", + "WAL" => "wallonne, Région", + "WBR" => "Brabant wallon", + "WHT" => "Hainaut", + "WLG" => "Liège", + "WLX" => "Luxembourg", + "WNA" => "Namur" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BF.php new file mode 100644 index 0000000..ded9e49 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BF.php @@ -0,0 +1,64 @@ + "Burkina Faso", + "subdivisions" => [ + "01" => "Boucle du Mouhoun", + "02" => "Cascades", + "03" => "Centre", + "04" => "Centre-Est", + "05" => "Centre-Nord", + "06" => "Centre-Ouest", + "07" => "Centre-Sud", + "08" => "Est", + "09" => "Hauts-Bassins", + "10" => "Nord", + "11" => "Plateau-Central", + "12" => "Sahel", + "13" => "Sud-Ouest", + "BAL" => "Balé", + "BAM" => "Bam", + "BAN" => "Banwa", + "BAZ" => "Bazèga", + "BGR" => "Bougouriba", + "BLG" => "Boulgou", + "BLK" => "Boulkiemdé", + "COM" => "Comoé", + "GAN" => "Ganzourgou", + "GNA" => "Gnagna", + "GOU" => "Gourma", + "HOU" => "Houet", + "IOB" => "Ioba", + "KAD" => "Kadiogo", + "KEN" => "Kénédougou", + "KMD" => "Komondjari", + "KMP" => "Kompienga", + "KOP" => "Koulpélogo", + "KOS" => "Kossi", + "KOT" => "Kouritenga", + "KOW" => "Kourwéogo", + "LER" => "Léraba", + "LOR" => "Loroum", + "MOU" => "Mouhoun", + "NAM" => "Namentenga", + "NAO" => "Nahouri", + "NAY" => "Nayala", + "NOU" => "Noumbiel", + "OUB" => "Oubritenga", + "OUD" => "Oudalan", + "PAS" => "Passoré", + "PON" => "Poni", + "SEN" => "Séno", + "SIS" => "Sissili", + "SMT" => "Sanmatenga", + "SNG" => "Sanguié", + "SOM" => "Soum", + "SOR" => "Sourou", + "TAP" => "Tapoa", + "TUI" => "Tuy", + "YAG" => "Yagha", + "YAT" => "Yatenga", + "ZIR" => "Ziro", + "ZON" => "Zondoma", + "ZOU" => "Zoundwéogo" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BG.php new file mode 100644 index 0000000..e5f2f92 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BG.php @@ -0,0 +1,34 @@ + "Bulgaria", + "subdivisions" => [ + "01" => "Blagoevgrad", + "02" => "Burgas", + "03" => "Varna", + "04" => "Veliko Tarnovo", + "05" => "Vidin", + "06" => "Vratsa", + "07" => "Gabrovo", + "08" => "Dobrich", + "09" => "Kardzhali", + "10" => "Kyustendil", + "11" => "Lovech", + "12" => "Montana", + "13" => "Pazardzhik", + "14" => "Pernik", + "15" => "Pleven", + "16" => "Plovdiv", + "17" => "Razgrad", + "18" => "Ruse", + "19" => "Silistra", + "20" => "Sliven", + "21" => "Smolyan", + "22" => "Sofia (stolitsa)", + "23" => "Sofia", + "24" => "Stara Zagora", + "25" => "Targovishte", + "26" => "Haskovo", + "27" => "Shumen", + "28" => "Yambol" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BH.php new file mode 100644 index 0000000..70302db --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BH.php @@ -0,0 +1,10 @@ + "Bahrain", + "subdivisions" => [ + "13" => "Al ‘Āşimah", + "14" => "Al Janūbīyah", + "15" => "Al Muḩarraq", + "17" => "Ash Shamālīyah" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BI.php new file mode 100644 index 0000000..6604d5f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BI.php @@ -0,0 +1,24 @@ + "Burundi", + "subdivisions" => [ + "BB" => "Bubanza", + "BL" => "Bujumbura Rural", + "BM" => "Bujumbura Mairie", + "BR" => "Bururi", + "CA" => "Cankuzo", + "CI" => "Cibitoke", + "GI" => "Gitega", + "KI" => "Kirundo", + "KR" => "Karuzi", + "KY" => "Kayanza", + "MA" => "Makamba", + "MU" => "Muramvya", + "MW" => "Mwaro", + "MY" => "Muyinga", + "NG" => "Ngozi", + "RM" => "Rumonge", + "RT" => "Rutana", + "RY" => "Ruyigi" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BJ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BJ.php new file mode 100644 index 0000000..26b02a4 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BJ.php @@ -0,0 +1,18 @@ + "Benin", + "subdivisions" => [ + "AK" => "Atacora", + "AL" => "Alibori", + "AQ" => "Atlantique", + "BO" => "Borgou", + "CO" => "Collines", + "DO" => "Donga", + "KO" => "Couffo", + "LI" => "Littoral", + "MO" => "Mono", + "OU" => "Ouémé", + "PL" => "Plateau", + "ZO" => "Zou" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BL.php new file mode 100644 index 0000000..200df0e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BL.php @@ -0,0 +1,6 @@ + "Saint Barthélemy", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BM.php new file mode 100644 index 0000000..0a00878 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BM.php @@ -0,0 +1,6 @@ + "Bermuda", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BN.php new file mode 100644 index 0000000..6318e0e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BN.php @@ -0,0 +1,10 @@ + "Brunei Darussalam", + "subdivisions" => [ + "BE" => "Belait", + "BM" => "Brunei-Muara", + "TE" => "Temburong", + "TU" => "Tutong" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BO.php new file mode 100644 index 0000000..8baa3e0 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BO.php @@ -0,0 +1,15 @@ + "Bolivia, Plurinational State of", + "subdivisions" => [ + "B" => "El Beni", + "C" => "Cochabamba", + "H" => "Chuquisaca", + "L" => "La Paz", + "N" => "Pando", + "O" => "Oruro", + "P" => "Potosí", + "S" => "Santa Cruz", + "T" => "Tarija" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BQ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BQ.php new file mode 100644 index 0000000..983a08d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BQ.php @@ -0,0 +1,9 @@ + "Bonaire, Sint Eustatius and Saba", + "subdivisions" => [ + "BO" => "Bonaire", + "SA" => "Saba", + "SE" => "Sint Eustatius" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BR.php new file mode 100644 index 0000000..99e152b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BR.php @@ -0,0 +1,33 @@ + "Brazil", + "subdivisions" => [ + "AC" => "Acre", + "AL" => "Alagoas", + "AM" => "Amazonas", + "AP" => "Amapá", + "BA" => "Bahia", + "CE" => "Ceará", + "DF" => "Distrito Federal", + "ES" => "Espírito Santo", + "GO" => "Goiás", + "MA" => "Maranhão", + "MG" => "Minas Gerais", + "MS" => "Mato Grosso do Sul", + "MT" => "Mato Grosso", + "PA" => "Pará", + "PB" => "Paraíba", + "PE" => "Pernambuco", + "PI" => "Piauí", + "PR" => "Paraná", + "RJ" => "Rio de Janeiro", + "RN" => "Rio Grande do Norte", + "RO" => "Rondônia", + "RR" => "Roraima", + "RS" => "Rio Grande do Sul", + "SC" => "Santa Catarina", + "SE" => "Sergipe", + "SP" => "São Paulo", + "TO" => "Tocantins" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BS.php new file mode 100644 index 0000000..94ca85d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BS.php @@ -0,0 +1,38 @@ + "Bahamas", + "subdivisions" => [ + "AK" => "Acklins", + "BI" => "Bimini", + "BP" => "Black Point", + "BY" => "Berry Islands", + "CE" => "Central Eleuthera", + "CI" => "Cat Island", + "CK" => "Crooked Island and Long Cay", + "CO" => "Central Abaco", + "CS" => "Central Andros", + "EG" => "East Grand Bahama", + "EX" => "Exuma", + "FP" => "City of Freeport", + "GC" => "Grand Cay", + "HI" => "Harbour Island", + "HT" => "Hope Town", + "IN" => "Inagua", + "LI" => "Long Island", + "MC" => "Mangrove Cay", + "MG" => "Mayaguana", + "MI" => "Moore's Island", + "NE" => "North Eleuthera", + "NO" => "North Abaco", + "NP" => "New Providence", + "NS" => "North Andros", + "RC" => "Rum Cay", + "RI" => "Ragged Island", + "SA" => "South Andros", + "SE" => "South Eleuthera", + "SO" => "South Abaco", + "SS" => "San Salvador", + "SW" => "Spanish Wells", + "WG" => "West Grand Bahama" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BT.php new file mode 100644 index 0000000..2b09526 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BT.php @@ -0,0 +1,26 @@ + "Bhutan", + "subdivisions" => [ + "11" => "Paro", + "12" => "Chhukha", + "13" => "Haa", + "14" => "Samtse", + "15" => "Thimphu", + "21" => "Tsirang", + "22" => "Dagana", + "23" => "Punakha", + "24" => "Wangdue Phodrang", + "31" => "Sarpang", + "32" => "Trongsa", + "33" => "Bumthang", + "34" => "Zhemgang", + "41" => "Trashigang", + "42" => "Monggar", + "43" => "Pema Gatshel", + "44" => "Lhuentse", + "45" => "Samdrup Jongkhar", + "GA" => "Gasa", + "TY" => "Trashi Yangtse" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BV.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BV.php new file mode 100644 index 0000000..2fcabda --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BV.php @@ -0,0 +1,6 @@ + "Bouvet Island", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BW.php new file mode 100644 index 0000000..2d60fd8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BW.php @@ -0,0 +1,22 @@ + "Botswana", + "subdivisions" => [ + "CE" => "Central", + "CH" => "Chobe", + "FR" => "Francistown", + "GA" => "Gaborone", + "GH" => "Ghanzi", + "JW" => "Jwaneng", + "KG" => "Kgalagadi", + "KL" => "Kgatleng", + "KW" => "Kweneng", + "LO" => "Lobatse", + "NE" => "North East", + "NW" => "North West", + "SE" => "South East", + "SO" => "Southern", + "SP" => "Selibe Phikwe", + "ST" => "Sowa Town" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BY.php new file mode 100644 index 0000000..94fc0b8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BY.php @@ -0,0 +1,13 @@ + "Belarus", + "subdivisions" => [ + "BR" => "Bresckaja voblasć", + "HM" => "Gorod Minsk", + "HO" => "Gomel'skaja oblast'", + "HR" => "Grodnenskaja oblast'", + "MA" => "Mahilioŭskaja voblasć", + "MI" => "Minskaja oblast'", + "VI" => "Viciebskaja voblasć" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/BZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/BZ.php new file mode 100644 index 0000000..cef38b7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/BZ.php @@ -0,0 +1,12 @@ + "Belize", + "subdivisions" => [ + "BZ" => "Belize", + "CY" => "Cayo", + "CZL" => "Corozal", + "OW" => "Orange Walk", + "SC" => "Stann Creek", + "TOL" => "Toledo" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CA.php new file mode 100644 index 0000000..e936a8f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CA.php @@ -0,0 +1,19 @@ + "Canada", + "subdivisions" => [ + "AB" => "Alberta", + "BC" => "British Columbia", + "MB" => "Manitoba", + "NB" => "New Brunswick", + "NL" => "Newfoundland and Labrador", + "NS" => "Nova Scotia", + "NT" => "Northwest Territories", + "NU" => "Nunavut", + "ON" => "Ontario", + "PE" => "Prince Edward Island", + "QC" => "Quebec", + "SK" => "Saskatchewan", + "YT" => "Yukon" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CC.php new file mode 100644 index 0000000..ed4f7a5 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CC.php @@ -0,0 +1,6 @@ + "Cocos (Keeling) Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CD.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CD.php new file mode 100644 index 0000000..cea0ac7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CD.php @@ -0,0 +1,32 @@ + "Congo, The Democratic Republic of the", + "subdivisions" => [ + "BC" => "Kongo Central", + "BU" => "Bas-Uélé", + "EQ" => "Équateur", + "HK" => "Haut-Katanga", + "HL" => "Haut-Lomami", + "HU" => "Haut-Uélé", + "IT" => "Ituri", + "KC" => "Kasaï Central", + "KE" => "Kasaï Oriental", + "KG" => "Kwango", + "KL" => "Kwilu", + "KN" => "Kinshasa", + "KS" => "Kasaï", + "LO" => "Lomami", + "LU" => "Lualaba", + "MA" => "Maniema", + "MN" => "Mai-Ndombe", + "MO" => "Mongala", + "NK" => "Nord-Kivu", + "NU" => "Nord-Ubangi", + "SA" => "Sankuru", + "SK" => "Sud-Kivu", + "SU" => "Sud-Ubangi", + "TA" => "Tanganyika", + "TO" => "Tshopo", + "TU" => "Tshuapa" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CF.php new file mode 100644 index 0000000..698d79c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CF.php @@ -0,0 +1,23 @@ + "Central African Republic", + "subdivisions" => [ + "AC" => "Ouham", + "BB" => "Bamingui-Bangoran", + "BGF" => "Bangui", + "BK" => "Basse-Kotto", + "HK" => "Haute-Kotto", + "HM" => "Haut-Mbomou", + "HS" => "Haute-Sangha / Mambéré-Kadéï", + "KB" => "Gribingui", + "KG" => "Kemö-Gïrïbïngï", + "LB" => "Lobaye", + "MB" => "Mbomou", + "MP" => "Ombella-Mpoko", + "NM" => "Nana-Mambéré", + "OP" => "Ouham-Pendé", + "SE" => "Sangha", + "UK" => "Ouaka", + "VK" => "Vakaga" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CG.php new file mode 100644 index 0000000..61e3ccc --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CG.php @@ -0,0 +1,18 @@ + "Congo", + "subdivisions" => [ + "11" => "Bouenza", + "12" => "Pool", + "13" => "Sangha", + "14" => "Plateaux", + "15" => "Cuvette-Ouest", + "16" => "Pointe-Noire", + "2" => "Lékoumou", + "5" => "Kouilou", + "7" => "Likouala", + "8" => "Cuvette", + "9" => "Niari", + "BZV" => "Brazzaville" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CH.php new file mode 100644 index 0000000..71aba7d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CH.php @@ -0,0 +1,32 @@ + "Switzerland", + "subdivisions" => [ + "AG" => "Aargau", + "AI" => "Appenzell Innerrhoden", + "AR" => "Appenzell Ausserrhoden", + "BE" => "Bern", + "BL" => "Basel-Landschaft", + "BS" => "Basel-Stadt", + "FR" => "Freiburg", + "GE" => "Genève", + "GL" => "Glarus", + "GR" => "Graubünden", + "JU" => "Jura", + "LU" => "Luzern", + "NE" => "Neuchâtel", + "NW" => "Nidwalden", + "OW" => "Obwalden", + "SG" => "Sankt Gallen", + "SH" => "Schaffhausen", + "SO" => "Solothurn", + "SZ" => "Schwyz", + "TG" => "Thurgau", + "TI" => "Ticino", + "UR" => "Uri", + "VD" => "Vaud", + "VS" => "Valais", + "ZG" => "Zug", + "ZH" => "Zürich" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CI.php new file mode 100644 index 0000000..192c4b8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CI.php @@ -0,0 +1,20 @@ + "Côte d'Ivoire", + "subdivisions" => [ + "AB" => "Abidjan", + "BS" => "Bas-Sassandra", + "CM" => "Comoé", + "DN" => "Denguélé", + "GD" => "Gôh-Djiboua", + "LC" => "Lacs", + "LG" => "Lagunes", + "MG" => "Montagnes", + "SM" => "Sassandra-Marahoué", + "SV" => "Savanes", + "VB" => "Vallée du Bandama", + "WR" => "Woroba", + "YM" => "Yamoussoukro", + "ZZ" => "Zanzan" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CK.php new file mode 100644 index 0000000..1cb9cd6 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CK.php @@ -0,0 +1,6 @@ + "Cook Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CL.php new file mode 100644 index 0000000..a8fe1d8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CL.php @@ -0,0 +1,22 @@ + "Chile", + "subdivisions" => [ + "AI" => "Aisén del General Carlos Ibañez del Campo", + "AN" => "Antofagasta", + "AP" => "Arica y Parinacota", + "AR" => "La Araucanía", + "AT" => "Atacama", + "BI" => "Biobío", + "CO" => "Coquimbo", + "LI" => "Libertador General Bernardo O'Higgins", + "LL" => "Los Lagos", + "LR" => "Los Ríos", + "MA" => "Magallanes", + "ML" => "Maule", + "NB" => "Ñuble", + "RM" => "Región Metropolitana de Santiago", + "TA" => "Tarapacá", + "VS" => "Valparaíso" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CM.php new file mode 100644 index 0000000..c323565 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CM.php @@ -0,0 +1,16 @@ + "Cameroon", + "subdivisions" => [ + "AD" => "Adamaoua", + "CE" => "Centre", + "EN" => "Far North", + "ES" => "East", + "LT" => "Littoral", + "NO" => "North", + "NW" => "North-West", + "OU" => "West", + "SU" => "South", + "SW" => "South-West" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CN.php new file mode 100644 index 0000000..75b684d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CN.php @@ -0,0 +1,40 @@ + "China", + "subdivisions" => [ + "AH" => "Anhui Sheng", + "BJ" => "Beijing Shi", + "CQ" => "Chongqing Shi", + "FJ" => "Fujian Sheng", + "GD" => "Guangdong Sheng", + "GS" => "Gansu Sheng", + "GX" => "Guangxi Zhuangzu Zizhiqu", + "GZ" => "Guizhou Sheng", + "HA" => "Henan Sheng", + "HB" => "Hubei Sheng", + "HE" => "Hebei Sheng", + "HI" => "Hainan Sheng", + "HK" => "Hong Kong SAR", + "HL" => "Heilongjiang Sheng", + "HN" => "Hunan Sheng", + "JL" => "Jilin Sheng", + "JS" => "Jiangsu Sheng", + "JX" => "Jiangxi Sheng", + "LN" => "Liaoning Sheng", + "MO" => "Macao SAR", + "NM" => "Nei Mongol Zizhiqu", + "NX" => "Ningxia Huizi Zizhiqu", + "QH" => "Qinghai Sheng", + "SC" => "Sichuan Sheng", + "SD" => "Shandong Sheng", + "SH" => "Shanghai Shi", + "SN" => "Shaanxi Sheng", + "SX" => "Shanxi Sheng", + "TJ" => "Tianjin Shi", + "TW" => "Taiwan Sheng", + "XJ" => "Xinjiang Uygur Zizhiqu", + "XZ" => "Xizang Zizhiqu", + "YN" => "Yunnan Sheng", + "ZJ" => "Zhejiang Sheng" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CO.php new file mode 100644 index 0000000..0b41056 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CO.php @@ -0,0 +1,39 @@ + "Colombia", + "subdivisions" => [ + "AMA" => "Amazonas", + "ANT" => "Antioquia", + "ARA" => "Arauca", + "ATL" => "Atlántico", + "BOL" => "Bolívar", + "BOY" => "Boyacá", + "CAL" => "Caldas", + "CAQ" => "Caquetá", + "CAS" => "Casanare", + "CAU" => "Cauca", + "CES" => "Cesar", + "CHO" => "Chocó", + "COR" => "Córdoba", + "CUN" => "Cundinamarca", + "DC" => "Distrito Capital de Bogotá", + "GUA" => "Guainía", + "GUV" => "Guaviare", + "HUI" => "Huila", + "LAG" => "La Guajira", + "MAG" => "Magdalena", + "MET" => "Meta", + "NAR" => "Nariño", + "NSA" => "Norte de Santander", + "PUT" => "Putumayo", + "QUI" => "Quindío", + "RIS" => "Risaralda", + "SAN" => "Santander", + "SAP" => "San Andrés, Providencia y Santa Catalina", + "SUC" => "Sucre", + "TOL" => "Tolima", + "VAC" => "Valle del Cauca", + "VAU" => "Vaupés", + "VID" => "Vichada" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CR.php new file mode 100644 index 0000000..342444a --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CR.php @@ -0,0 +1,13 @@ + "Costa Rica", + "subdivisions" => [ + "A" => "Alajuela", + "C" => "Cartago", + "G" => "Guanacaste", + "H" => "Heredia", + "L" => "Limón", + "P" => "Puntarenas", + "SJ" => "San José" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CU.php new file mode 100644 index 0000000..8158d2c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CU.php @@ -0,0 +1,22 @@ + "Cuba", + "subdivisions" => [ + "01" => "Pinar del Río", + "03" => "La Habana", + "04" => "Matanzas", + "05" => "Villa Clara", + "06" => "Cienfuegos", + "07" => "Sancti Spíritus", + "08" => "Ciego de Ávila", + "09" => "Camagüey", + "10" => "Las Tunas", + "11" => "Holguín", + "12" => "Granma", + "13" => "Santiago de Cuba", + "14" => "Guantánamo", + "15" => "Artemisa", + "16" => "Mayabeque", + "99" => "Isla de la Juventud" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CV.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CV.php new file mode 100644 index 0000000..2fb6111 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CV.php @@ -0,0 +1,30 @@ + "Cabo Verde", + "subdivisions" => [ + "B" => "Ilhas de Barlavento", + "BR" => "Brava", + "BV" => "Boa Vista", + "CA" => "Santa Catarina", + "CF" => "Santa Catarina do Fogo", + "CR" => "Santa Cruz", + "MA" => "Maio", + "MO" => "Mosteiros", + "PA" => "Paul", + "PN" => "Porto Novo", + "PR" => "Praia", + "RB" => "Ribeira Brava", + "RG" => "Ribeira Grande", + "RS" => "Ribeira Grande de Santiago", + "S" => "Ilhas de Sotavento", + "SD" => "São Domingos", + "SF" => "São Filipe", + "SL" => "Sal", + "SM" => "São Miguel", + "SO" => "São Lourenço dos Órgãos", + "SS" => "São Salvador do Mundo", + "SV" => "São Vicente", + "TA" => "Tarrafal", + "TS" => "Tarrafal de São Nicolau" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CW.php new file mode 100644 index 0000000..a9e06ef --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CW.php @@ -0,0 +1,6 @@ + "Curaçao", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CX.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CX.php new file mode 100644 index 0000000..b226971 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CX.php @@ -0,0 +1,6 @@ + "Christmas Island", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CY.php new file mode 100644 index 0000000..8e9a4c5 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CY.php @@ -0,0 +1,12 @@ + "Cyprus", + "subdivisions" => [ + "01" => "Lefkosia", + "02" => "Lemesos", + "03" => "Larnaka", + "04" => "Ammochostos", + "05" => "Baf", + "06" => "Girne" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/CZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/CZ.php new file mode 100644 index 0000000..f532a4a --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/CZ.php @@ -0,0 +1,96 @@ + "Czechia", + "subdivisions" => [ + "10" => "Praha, Hlavní město", + "20" => "Středočeský kraj", + "201" => "Benešov", + "202" => "Beroun", + "203" => "Kladno", + "204" => "Kolín", + "205" => "Kutná Hora", + "206" => "Mělník", + "207" => "Mladá Boleslav", + "208" => "Nymburk", + "209" => "Praha-východ", + "20A" => "Praha-západ", + "20B" => "Příbram", + "20C" => "Rakovník", + "31" => "Jihočeský kraj", + "311" => "České Budějovice", + "312" => "Český Krumlov", + "313" => "Jindřichův Hradec", + "314" => "Písek", + "315" => "Prachatice", + "316" => "Strakonice", + "317" => "Tábor", + "32" => "Plzeňský kraj", + "321" => "Domažlice", + "322" => "Klatovy", + "323" => "Plzeň-město", + "324" => "Plzeň-jih", + "325" => "Plzeň-sever", + "326" => "Rokycany", + "327" => "Tachov", + "41" => "Karlovarský kraj", + "411" => "Cheb", + "412" => "Karlovy Vary", + "413" => "Sokolov", + "42" => "Ústecký kraj", + "421" => "Děčín", + "422" => "Chomutov", + "423" => "Litoměřice", + "424" => "Louny", + "425" => "Most", + "426" => "Teplice", + "427" => "Ústí nad Labem", + "51" => "Liberecký kraj", + "511" => "Česká Lípa", + "512" => "Jablonec nad Nisou", + "513" => "Liberec", + "514" => "Semily", + "52" => "Královéhradecký kraj", + "521" => "Hradec Králové", + "522" => "Jičín", + "523" => "Náchod", + "524" => "Rychnov nad Kněžnou", + "525" => "Trutnov", + "53" => "Pardubický kraj", + "531" => "Chrudim", + "532" => "Pardubice", + "533" => "Svitavy", + "534" => "Ústí nad Orlicí", + "63" => "Kraj Vysočina", + "631" => "Havlíčkův Brod", + "632" => "Jihlava", + "633" => "Pelhřimov", + "634" => "Třebíč", + "635" => "Žďár nad Sázavou", + "64" => "Jihomoravský kraj", + "641" => "Blansko", + "642" => "Brno-město", + "643" => "Brno-venkov", + "644" => "Břeclav", + "645" => "Hodonín", + "646" => "Vyškov", + "647" => "Znojmo", + "71" => "Olomoucký kraj", + "711" => "Jeseník", + "712" => "Olomouc", + "713" => "Prostějov", + "714" => "Přerov", + "715" => "Šumperk", + "72" => "Zlínský kraj", + "721" => "Kroměříž", + "722" => "Uherské Hradiště", + "723" => "Vsetín", + "724" => "Zlín", + "80" => "Moravskoslezský kraj", + "801" => "Bruntál", + "802" => "Frýdek-Místek", + "803" => "Karviná", + "804" => "Nový Jičín", + "805" => "Opava", + "806" => "Ostrava-město" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/DE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/DE.php new file mode 100644 index 0000000..fe5c855 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/DE.php @@ -0,0 +1,22 @@ + "Germany", + "subdivisions" => [ + "BB" => "Brandenburg", + "BE" => "Berlin", + "BW" => "Baden-Württemberg", + "BY" => "Bayern", + "HB" => "Bremen", + "HE" => "Hessen", + "HH" => "Hamburg", + "MV" => "Mecklenburg-Vorpommern", + "NI" => "Niedersachsen", + "NW" => "Nordrhein-Westfalen", + "RP" => "Rheinland-Pfalz", + "SH" => "Schleswig-Holstein", + "SL" => "Saarland", + "SN" => "Sachsen", + "ST" => "Sachsen-Anhalt", + "TH" => "Thüringen" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/DJ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/DJ.php new file mode 100644 index 0000000..9eba57d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/DJ.php @@ -0,0 +1,12 @@ + "Djibouti", + "subdivisions" => [ + "AR" => "Arta", + "AS" => "Ali Sabieh", + "DI" => "Dikhil", + "DJ" => "Djibouti", + "OB" => "Awbūk", + "TA" => "Tadjourah" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/DK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/DK.php new file mode 100644 index 0000000..771fa45 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/DK.php @@ -0,0 +1,11 @@ + "Denmark", + "subdivisions" => [ + "81" => "Nordjylland", + "82" => "Midtjylland", + "83" => "Syddanmark", + "84" => "Hovedstaden", + "85" => "Sjælland" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/DM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/DM.php new file mode 100644 index 0000000..cd95930 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/DM.php @@ -0,0 +1,16 @@ + "Dominica", + "subdivisions" => [ + "02" => "Saint Andrew", + "03" => "Saint David", + "04" => "Saint George", + "05" => "Saint John", + "06" => "Saint Joseph", + "07" => "Saint Luke", + "08" => "Saint Mark", + "09" => "Saint Patrick", + "10" => "Saint Paul", + "11" => "Saint Peter" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/DO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/DO.php new file mode 100644 index 0000000..8698a86 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/DO.php @@ -0,0 +1,48 @@ + "Dominican Republic", + "subdivisions" => [ + "01" => "Distrito Nacional (Santo Domingo)", + "02" => "Azua", + "03" => "Baoruco", + "04" => "Barahona", + "05" => "Dajabón", + "06" => "Duarte", + "07" => "Elías Piña", + "08" => "El Seibo", + "09" => "Espaillat", + "10" => "Independencia", + "11" => "La Altagracia", + "12" => "La Romana", + "13" => "La Vega", + "14" => "María Trinidad Sánchez", + "15" => "Monte Cristi", + "16" => "Pedernales", + "17" => "Peravia", + "18" => "Puerto Plata", + "19" => "Hermanas Mirabal", + "20" => "Samaná", + "21" => "San Cristóbal", + "22" => "San Juan", + "23" => "San Pedro de Macorís", + "24" => "Sánchez Ramírez", + "25" => "Santiago", + "26" => "Santiago Rodríguez", + "27" => "Valverde", + "28" => "Monseñor Nouel", + "29" => "Monte Plata", + "30" => "Hato Mayor", + "31" => "San José de Ocoa", + "32" => "Santo Domingo", + "33" => "Cibao Nordeste", + "34" => "Cibao Noroeste", + "35" => "Cibao Norte", + "36" => "Cibao Sur", + "37" => "El Valle", + "38" => "Enriquillo", + "39" => "Higuamo", + "40" => "Ozama", + "41" => "Valdesia", + "42" => "Yuma" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/DZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/DZ.php new file mode 100644 index 0000000..766ca0e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/DZ.php @@ -0,0 +1,54 @@ + "Algeria", + "subdivisions" => [ + "01" => "Adrar", + "02" => "Chlef", + "03" => "Laghouat", + "04" => "Oum el Bouaghi", + "05" => "Batna", + "06" => "Béjaïa", + "07" => "Biskra", + "08" => "Béchar", + "09" => "Blida", + "10" => "Bouira", + "11" => "Tamanrasset", + "12" => "Tébessa", + "13" => "Tlemcen", + "14" => "Tiaret", + "15" => "Tizi Ouzou", + "16" => "Alger", + "17" => "Djelfa", + "18" => "Jijel", + "19" => "Sétif", + "20" => "Saïda", + "21" => "Skikda", + "22" => "Sidi Bel Abbès", + "23" => "Annaba", + "24" => "Guelma", + "25" => "Constantine", + "26" => "Médéa", + "27" => "Mostaganem", + "28" => "M'sila", + "29" => "Mascara", + "30" => "Ouargla", + "31" => "Oran", + "32" => "El Bayadh", + "33" => "Illizi", + "34" => "Bordj Bou Arréridj", + "35" => "Boumerdès", + "36" => "El Tarf", + "37" => "Tindouf", + "38" => "Tissemsilt", + "39" => "El Oued", + "40" => "Khenchela", + "41" => "Souk Ahras", + "42" => "Tipaza", + "43" => "Mila", + "44" => "Aïn Defla", + "45" => "Naama", + "46" => "Aïn Témouchent", + "47" => "Ghardaïa", + "48" => "Relizane" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/EC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/EC.php new file mode 100644 index 0000000..4104bed --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/EC.php @@ -0,0 +1,30 @@ + "Ecuador", + "subdivisions" => [ + "A" => "Azuay", + "B" => "Bolívar", + "C" => "Carchi", + "D" => "Orellana", + "E" => "Esmeraldas", + "F" => "Cañar", + "G" => "Guayas", + "H" => "Chimborazo", + "I" => "Imbabura", + "L" => "Loja", + "M" => "Manabí", + "N" => "Napo", + "O" => "El Oro", + "P" => "Pichincha", + "R" => "Los Ríos", + "S" => "Morona Santiago", + "SD" => "Santo Domingo de los Tsáchilas", + "SE" => "Santa Elena", + "T" => "Tungurahua", + "U" => "Sucumbíos", + "W" => "Galápagos", + "X" => "Cotopaxi", + "Y" => "Pastaza", + "Z" => "Zamora Chinchipe" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/EE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/EE.php new file mode 100644 index 0000000..4e90f79 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/EE.php @@ -0,0 +1,100 @@ + "Estonia", + "subdivisions" => [ + "130" => "Alutaguse", + "141" => "Anija", + "142" => "Antsla", + "171" => "Elva", + "184" => "Haapsalu", + "191" => "Haljala", + "198" => "Harku", + "205" => "Hiiumaa", + "214" => "Häädemeeste", + "245" => "Jõelähtme", + "247" => "Jõgeva", + "251" => "Jõhvi", + "255" => "Järva", + "272" => "Kadrina", + "283" => "Kambja", + "284" => "Kanepi", + "291" => "Kastre", + "293" => "Kehtna", + "296" => "Keila", + "303" => "Kihnu", + "305" => "Kiili", + "317" => "Kohila", + "321" => "Kohtla-Järve", + "338" => "Kose", + "353" => "Kuusalu", + "37" => "Harjumaa", + "39" => "Hiiumaa", + "424" => "Loksa", + "430" => "Lääneranna", + "431" => "Lääne-Harju", + "432" => "Luunja", + "441" => "Lääne-Nigula", + "442" => "Lüganuse", + "446" => "Maardu", + "45" => "Ida-Virumaa", + "478" => "Muhu", + "480" => "Mulgi", + "486" => "Mustvee", + "50" => "Jõgevamaa", + "503" => "Märjamaa", + "511" => "Narva", + "514" => "Narva-Jõesuu", + "52" => "Järvamaa", + "528" => "Nõo", + "557" => "Otepää", + "56" => "Läänemaa", + "567" => "Paide", + "586" => "Peipsiääre", + "60" => "Lääne-Virumaa", + "615" => "Põhja-Sakala", + "618" => "Põltsamaa", + "622" => "Põlva", + "624" => "Pärnu", + "638" => "Põhja-Pärnumaa", + "64" => "Põlvamaa", + "651" => "Raasiku", + "653" => "Rae", + "661" => "Rakvere", + "663" => "Rakvere", + "668" => "Rapla", + "68" => "Pärnumaa", + "689" => "Ruhnu", + "698" => "Rõuge", + "708" => "Räpina", + "71" => "Raplamaa", + "712" => "Saarde", + "714" => "Saaremaa", + "719" => "Saku", + "726" => "Saue", + "732" => "Setomaa", + "735" => "Sillamäe", + "74" => "Saaremaa", + "784" => "Tallinn", + "79" => "Tartumaa", + "792" => "Tapa", + "793" => "Tartu", + "796" => "Tartu", + "803" => "Toila", + "809" => "Tori", + "81" => "Valgamaa", + "824" => "Tõrva", + "834" => "Türi", + "84" => "Viljandimaa", + "855" => "Valga", + "87" => "Võrumaa", + "890" => "Viimsi", + "897" => "Viljandi", + "899" => "Viljandi", + "901" => "Vinni", + "903" => "Viru-Nigula", + "907" => "Vormsi", + "917" => "Võru", + "919" => "Võru", + "928" => "Väike-Maarja" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/EG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/EG.php new file mode 100644 index 0000000..e0fdf93 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/EG.php @@ -0,0 +1,33 @@ + "Egypt", + "subdivisions" => [ + "ALX" => "Al Iskandarīyah", + "ASN" => "Aswān", + "AST" => "Asyūţ", + "BA" => "Al Baḩr al Aḩmar", + "BH" => "Al Buḩayrah", + "BNS" => "Banī Suwayf", + "C" => "Al Qāhirah", + "DK" => "Ad Daqahlīyah", + "DT" => "Dumyāţ", + "FYM" => "Al Fayyūm", + "GH" => "Al Gharbīyah", + "GZ" => "Al Jīzah", + "IS" => "Al Ismā'īlīyah", + "JS" => "Janūb Sīnā'", + "KB" => "Al Qalyūbīyah", + "KFS" => "Kafr ash Shaykh", + "KN" => "Qinā", + "LX" => "Al Uqşur", + "MN" => "Al Minyā", + "MNF" => "Al Minūfīyah", + "MT" => "Maţrūḩ", + "PTS" => "Būr Sa‘īd", + "SHG" => "Sūhāj", + "SHR" => "Ash Sharqīyah", + "SIN" => "Shamāl Sīnā'", + "SUZ" => "As Suways", + "WAD" => "Al Wādī al Jadīd" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/EH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/EH.php new file mode 100644 index 0000000..43bf8e2 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/EH.php @@ -0,0 +1,6 @@ + "Western Sahara", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ER.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ER.php new file mode 100644 index 0000000..274973d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ER.php @@ -0,0 +1,12 @@ + "Eritrea", + "subdivisions" => [ + "AN" => "Ansabā", + "DK" => "Debubawi K’eyyĭḥ Baḥri", + "DU" => "Al Janūbī", + "GB" => "Gash-Barka", + "MA" => "Al Awsaţ", + "SK" => "Semienawi K’eyyĭḥ Baḥri" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ES.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ES.php new file mode 100644 index 0000000..02f43a8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ES.php @@ -0,0 +1,75 @@ + "Spain", + "subdivisions" => [ + "A" => "Alacant*", + "AB" => "Albacete", + "AL" => "Almería", + "AN" => "Andalucía", + "AR" => "Aragón", + "AS" => "Asturias, Principado de", + "AV" => "Ávila", + "B" => "Barcelona [Barcelona]", + "BA" => "Badajoz", + "BI" => "Bizkaia", + "BU" => "Burgos", + "C" => "A Coruña [La Coruña]", + "CA" => "Cádiz", + "CB" => "Cantabria", + "CC" => "Cáceres", + "CE" => "Ceuta", + "CL" => "Castilla y León", + "CM" => "Castilla-La Mancha", + "CN" => "Canarias", + "CO" => "Córdoba", + "CR" => "Ciudad Real", + "CS" => "Castelló*", + "CT" => "Catalunya [Cataluña]", + "CU" => "Cuenca", + "EX" => "Extremadura", + "GA" => "Galicia [Galicia]", + "GC" => "Las Palmas", + "GI" => "Girona [Gerona]", + "GR" => "Granada", + "GU" => "Guadalajara", + "H" => "Huelva", + "HU" => "Huesca", + "IB" => "Illes Balears [Islas Baleares]", + "J" => "Jaén", + "L" => "Lleida [Lérida]", + "LE" => "León", + "LO" => "La Rioja", + "LU" => "Lugo [Lugo]", + "M" => "Madrid", + "MA" => "Málaga", + "MC" => "Murcia, Región de", + "MD" => "Madrid, Comunidad de", + "ML" => "Melilla", + "MU" => "Murcia", + "NA" => "Nafarroa*", + "NC" => "Nafarroako Foru Komunitatea*", + "O" => "Asturias", + "OR" => "Ourense [Orense]", + "P" => "Palencia", + "PM" => "Illes Balears [Islas Baleares]", + "PO" => "Pontevedra [Pontevedra]", + "PV" => "Euskal Herria", + "RI" => "La Rioja", + "S" => "Cantabria", + "SA" => "Salamanca", + "SE" => "Sevilla", + "SG" => "Segovia", + "SO" => "Soria", + "SS" => "Gipuzkoa", + "T" => "Tarragona [Tarragona]", + "TE" => "Teruel", + "TF" => "Santa Cruz de Tenerife", + "TO" => "Toledo", + "V" => "Valencia", + "VA" => "Valladolid", + "VC" => "Valenciana, Comunidad", + "VI" => "Araba*", + "Z" => "Zaragoza", + "ZA" => "Zamora" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ET.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ET.php new file mode 100644 index 0000000..85b5322 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ET.php @@ -0,0 +1,17 @@ + "Ethiopia", + "subdivisions" => [ + "AA" => "Addis Ababa", + "AF" => "Afar", + "AM" => "Amara", + "BE" => "Benshangul-Gumaz", + "DD" => "Dire Dawa", + "GA" => "Gambela Peoples", + "HA" => "Harari People", + "OR" => "Oromia", + "SN" => "Southern Nations, Nationalities and Peoples", + "SO" => "Somali", + "TI" => "Tigrai" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/FI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/FI.php new file mode 100644 index 0000000..21287a6 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/FI.php @@ -0,0 +1,25 @@ + "Finland", + "subdivisions" => [ + "01" => "Åland", + "02" => "Etelä-Karjala", + "03" => "Etelä-Pohjanmaa", + "04" => "Etelä-Savo", + "05" => "Kainuu", + "06" => "Kanta-Häme", + "07" => "Keski-Pohjanmaa", + "08" => "Keski-Suomi", + "09" => "Kymenlaakso", + "10" => "Lappi", + "11" => "Pirkanmaa", + "12" => "Pohjanmaa", + "13" => "Pohjois-Karjala", + "14" => "Pohjois-Pohjanmaa", + "15" => "Pohjois-Savo", + "16" => "Päijät-Häme", + "17" => "Satakunta", + "18" => "Uusimaa", + "19" => "Varsinais-Suomi" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/FJ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/FJ.php new file mode 100644 index 0000000..34a180a --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/FJ.php @@ -0,0 +1,25 @@ + "Fiji", + "subdivisions" => [ + "01" => "Ba", + "02" => "Bua", + "03" => "Cakaudrove", + "04" => "Kadavu", + "05" => "Lau", + "06" => "Lomaiviti", + "07" => "Macuata", + "08" => "Nadroga and Navosa", + "09" => "Naitasiri", + "10" => "Namosi", + "11" => "Ra", + "12" => "Rewa", + "13" => "Serua", + "14" => "Tailevu", + "C" => "Central", + "E" => "Eastern", + "N" => "Northern", + "R" => "Rotuma", + "W" => "Western" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/FK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/FK.php new file mode 100644 index 0000000..19b63fa --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/FK.php @@ -0,0 +1,6 @@ + "Falkland Islands (Malvinas)", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/FM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/FM.php new file mode 100644 index 0000000..61c9116 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/FM.php @@ -0,0 +1,10 @@ + "Micronesia, Federated States of", + "subdivisions" => [ + "KSA" => "Kosrae", + "PNI" => "Pohnpei", + "TRK" => "Chuuk", + "YAP" => "Yap" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/FO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/FO.php new file mode 100644 index 0000000..15a3e40 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/FO.php @@ -0,0 +1,6 @@ + "Faroe Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/FR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/FR.php new file mode 100644 index 0000000..8526e82 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/FR.php @@ -0,0 +1,133 @@ + "France", + "subdivisions" => [ + "01" => "Ain", + "02" => "Aisne", + "03" => "Allier", + "04" => "Alpes-de-Haute-Provence", + "05" => "Hautes-Alpes", + "06" => "Alpes-Maritimes", + "07" => "Ardèche", + "08" => "Ardennes", + "09" => "Ariège", + "10" => "Aube", + "11" => "Aude", + "12" => "Aveyron", + "13" => "Bouches-du-Rhône", + "14" => "Calvados", + "15" => "Cantal", + "16" => "Charente", + "17" => "Charente-Maritime", + "18" => "Cher", + "19" => "Corrèze", + "20R" => "Corse", + "21" => "Côte-d'Or", + "22" => "Côtes-d'Armor", + "23" => "Creuse", + "24" => "Dordogne", + "25" => "Doubs", + "26" => "Drôme", + "27" => "Eure", + "28" => "Eure-et-Loir", + "29" => "Finistère", + "2A" => "Corse-du-Sud", + "2B" => "Haute-Corse", + "30" => "Gard", + "31" => "Haute-Garonne", + "32" => "Gers", + "33" => "Gironde", + "34" => "Hérault", + "35" => "Ille-et-Vilaine", + "36" => "Indre", + "37" => "Indre-et-Loire", + "38" => "Isère", + "39" => "Jura", + "40" => "Landes", + "41" => "Loir-et-Cher", + "42" => "Loire", + "43" => "Haute-Loire", + "44" => "Loire-Atlantique", + "45" => "Loiret", + "46" => "Lot", + "47" => "Lot-et-Garonne", + "48" => "Lozère", + "49" => "Maine-et-Loire", + "50" => "Manche", + "51" => "Marne", + "52" => "Haute-Marne", + "53" => "Mayenne", + "54" => "Meurthe-et-Moselle", + "55" => "Meuse", + "56" => "Morbihan", + "57" => "Moselle", + "58" => "Nièvre", + "59" => "Nord", + "60" => "Oise", + "61" => "Orne", + "62" => "Pas-de-Calais", + "63" => "Puy-de-Dôme", + "64" => "Pyrénées-Atlantiques", + "65" => "Hautes-Pyrénées", + "66" => "Pyrénées-Orientales", + "67" => "Bas-Rhin", + "68" => "Haut-Rhin", + "69" => "Rhône", + "70" => "Haute-Saône", + "71" => "Saône-et-Loire", + "72" => "Sarthe", + "73" => "Savoie", + "74" => "Haute-Savoie", + "75" => "Paris", + "76" => "Seine-Maritime", + "77" => "Seine-et-Marne", + "78" => "Yvelines", + "79" => "Deux-Sèvres", + "80" => "Somme", + "81" => "Tarn", + "82" => "Tarn-et-Garonne", + "83" => "Var", + "84" => "Vaucluse", + "85" => "Vendée", + "86" => "Vienne", + "87" => "Haute-Vienne", + "88" => "Vosges", + "89" => "Yonne", + "90" => "Territoire de Belfort", + "91" => "Essonne", + "92" => "Hauts-de-Seine", + "93" => "Seine-Saint-Denis", + "94" => "Val-de-Marne", + "95" => "Val-d'Oise", + "971" => "Guadeloupe", + "972" => "Martinique", + "973" => "Guyane (française)", + "974" => "La Réunion", + "976" => "Mayotte", + "ARA" => "Auvergne-Rhône-Alpes", + "BFC" => "Bourgogne-Franche-Comté", + "BL" => "Saint-Barthélemy", + "BRE" => "Bretagne", + "CP" => "Clipperton", + "CVL" => "Centre-Val de Loire", + "GES" => "Grand-Est", + "GF" => "Guyane (française)", + "GP" => "Guadeloupe", + "HDF" => "Hauts-de-France", + "IDF" => "Île-de-France", + "MF" => "Saint-Martin", + "MQ" => "Martinique", + "NAQ" => "Nouvelle-Aquitaine", + "NC" => "Nouvelle-Calédonie", + "NOR" => "Normandie", + "OCC" => "Occitanie", + "PAC" => "Provence-Alpes-Côte-d’Azur", + "PDL" => "Pays-de-la-Loire", + "PF" => "Polynésie française", + "PM" => "Saint-Pierre-et-Miquelon", + "RE" => "La Réunion", + "TF" => "Terres australes françaises", + "WF" => "Wallis-et-Futuna", + "YT" => "Mayotte" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GA.php new file mode 100644 index 0000000..db88eb0 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GA.php @@ -0,0 +1,15 @@ + "Gabon", + "subdivisions" => [ + "1" => "Estuaire", + "2" => "Haut-Ogooué", + "3" => "Moyen-Ogooué", + "4" => "Ngounié", + "5" => "Nyanga", + "6" => "Ogooué-Ivindo", + "7" => "Ogooué-Lolo", + "8" => "Ogooué-Maritime", + "9" => "Woleu-Ntem" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GB.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GB.php new file mode 100644 index 0000000..269753e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GB.php @@ -0,0 +1,226 @@ + "United Kingdom", + "subdivisions" => [ + "ABC" => "Armagh City, Banbridge and Craigavon", + "ABD" => "Aberdeenshire", + "ABE" => "Aberdeen City", + "AGB" => "Argyll and Bute", + "AGY" => "Isle of Anglesey [Sir Ynys Môn GB-YNM]", + "AND" => "Ards and North Down", + "ANN" => "Antrim and Newtownabbey", + "ANS" => "Angus", + "BAS" => "Bath and North East Somerset", + "BBD" => "Blackburn with Darwen", + "BCP" => "Bournemouth, Christchurch and Poole", + "BDF" => "Bedford", + "BDG" => "Barking and Dagenham", + "BEN" => "Brent", + "BEX" => "Bexley", + "BFS" => "Belfast City", + "BGE" => "Bridgend [Pen-y-bont ar Ogwr GB-POG]", + "BGW" => "Blaenau Gwent", + "BIR" => "Birmingham", + "BKM" => "Buckinghamshire", + "BNE" => "Barnet", + "BNH" => "Brighton and Hove", + "BNS" => "Barnsley", + "BOL" => "Bolton", + "BPL" => "Blackpool", + "BRC" => "Bracknell Forest", + "BRD" => "Bradford", + "BRY" => "Bromley", + "BST" => "Bristol, City of", + "BUR" => "Bury", + "CAM" => "Cambridgeshire", + "CAY" => "Caerphilly [Caerffili GB-CAF]", + "CBF" => "Central Bedfordshire", + "CCG" => "Causeway Coast and Glens", + "CGN" => "Ceredigion [Sir Ceredigion]", + "CHE" => "Cheshire East", + "CHW" => "Cheshire West and Chester", + "CLD" => "Calderdale", + "CLK" => "Clackmannanshire", + "CMA" => "Cumbria", + "CMD" => "Camden", + "CMN" => "Carmarthenshire [Sir Gaerfyrddin GB-GFY]", + "CON" => "Cornwall", + "COV" => "Coventry", + "CRF" => "Cardiff [Caerdydd GB-CRD]", + "CRY" => "Croydon", + "CWY" => "Conwy", + "DAL" => "Darlington", + "DBY" => "Derbyshire", + "DEN" => "Denbighshire [Sir Ddinbych GB-DDB]", + "DER" => "Derby", + "DEV" => "Devon", + "DGY" => "Dumfries and Galloway", + "DNC" => "Doncaster", + "DND" => "Dundee City", + "DOR" => "Dorset", + "DRS" => "Derry and Strabane", + "DUD" => "Dudley", + "DUR" => "Durham, County", + "EAL" => "Ealing", + "EAY" => "East Ayrshire", + "EDH" => "Edinburgh, City of", + "EDU" => "East Dunbartonshire", + "ELN" => "East Lothian", + "ELS" => "Eilean Siar", + "ENF" => "Enfield", + "ENG" => "England", + "ERW" => "East Renfrewshire", + "ERY" => "East Riding of Yorkshire", + "ESS" => "Essex", + "ESX" => "East Sussex", + "FAL" => "Falkirk", + "FIF" => "Fife", + "FLN" => "Flintshire [Sir y Fflint GB-FFL]", + "FMO" => "Fermanagh and Omagh", + "GAT" => "Gateshead", + "GLG" => "Glasgow City", + "GLS" => "Gloucestershire", + "GRE" => "Greenwich", + "GWN" => "Gwynedd", + "HAL" => "Halton", + "HAM" => "Hampshire", + "HAV" => "Havering", + "HCK" => "Hackney", + "HEF" => "Herefordshire", + "HIL" => "Hillingdon", + "HLD" => "Highland", + "HMF" => "Hammersmith and Fulham", + "HNS" => "Hounslow", + "HPL" => "Hartlepool", + "HRT" => "Hertfordshire", + "HRW" => "Harrow", + "HRY" => "Haringey", + "IOS" => "Isles of Scilly", + "IOW" => "Isle of Wight", + "ISL" => "Islington", + "IVC" => "Inverclyde", + "KEC" => "Kensington and Chelsea", + "KEN" => "Kent", + "KHL" => "Kingston upon Hull", + "KIR" => "Kirklees", + "KTT" => "Kingston upon Thames", + "KWL" => "Knowsley", + "LAN" => "Lancashire", + "LBC" => "Lisburn and Castlereagh", + "LBH" => "Lambeth", + "LCE" => "Leicester", + "LDS" => "Leeds", + "LEC" => "Leicestershire", + "LEW" => "Lewisham", + "LIN" => "Lincolnshire", + "LIV" => "Liverpool", + "LND" => "London, City of", + "LUT" => "Luton", + "MAN" => "Manchester", + "MDB" => "Middlesbrough", + "MDW" => "Medway", + "MEA" => "Mid and East Antrim", + "MIK" => "Milton Keynes", + "MLN" => "Midlothian", + "MON" => "Monmouthshire [Sir Fynwy GB-FYN]", + "MRT" => "Merton", + "MRY" => "Moray", + "MTY" => "Merthyr Tydfil [Merthyr Tudful GB-MTU]", + "MUL" => "Mid-Ulster", + "NAY" => "North Ayrshire", + "NBL" => "Northumberland", + "NEL" => "North East Lincolnshire", + "NET" => "Newcastle upon Tyne", + "NFK" => "Norfolk", + "NGM" => "Nottingham", + "NIR" => "Northern Ireland", + "NLK" => "North Lanarkshire", + "NLN" => "North Lincolnshire", + "NMD" => "Newry, Mourne and Down", + "NSM" => "North Somerset", + "NTH" => "Northamptonshire", + "NTL" => "Neath Port Talbot [Castell-nedd Port Talbot GB-CTL]", + "NTT" => "Nottinghamshire", + "NTY" => "North Tyneside", + "NWM" => "Newham", + "NWP" => "Newport [Casnewydd GB-CNW]", + "NYK" => "North Yorkshire", + "OLD" => "Oldham", + "ORK" => "Orkney Islands", + "OXF" => "Oxfordshire", + "PEM" => "Pembrokeshire [Sir Benfro GB-BNF]", + "PKN" => "Perth and Kinross", + "PLY" => "Plymouth", + "POR" => "Portsmouth", + "POW" => "Powys", + "PTE" => "Peterborough", + "RCC" => "Redcar and Cleveland", + "RCH" => "Rochdale", + "RCT" => "Rhondda Cynon Taff [Rhondda CynonTaf]", + "RDB" => "Redbridge", + "RDG" => "Reading", + "RFW" => "Renfrewshire", + "RIC" => "Richmond upon Thames", + "ROT" => "Rotherham", + "RUT" => "Rutland", + "SAW" => "Sandwell", + "SAY" => "South Ayrshire", + "SCB" => "Scottish Borders", + "SCT" => "Scotland", + "SFK" => "Suffolk", + "SFT" => "Sefton", + "SGC" => "South Gloucestershire", + "SHF" => "Sheffield", + "SHN" => "St. Helens", + "SHR" => "Shropshire", + "SKP" => "Stockport", + "SLF" => "Salford", + "SLG" => "Slough", + "SLK" => "South Lanarkshire", + "SND" => "Sunderland", + "SOL" => "Solihull", + "SOM" => "Somerset", + "SOS" => "Southend-on-Sea", + "SRY" => "Surrey", + "STE" => "Stoke-on-Trent", + "STG" => "Stirling", + "STH" => "Southampton", + "STN" => "Sutton", + "STS" => "Staffordshire", + "STT" => "Stockton-on-Tees", + "STY" => "South Tyneside", + "SWA" => "Swansea [Abertawe GB-ATA]", + "SWD" => "Swindon", + "SWK" => "Southwark", + "TAM" => "Tameside", + "TFW" => "Telford and Wrekin", + "THR" => "Thurrock", + "TOB" => "Torbay", + "TOF" => "Torfaen [Tor-faen]", + "TRF" => "Trafford", + "TWH" => "Tower Hamlets", + "VGL" => "Vale of Glamorgan, The [Bro Morgannwg GB-BMG]", + "WAR" => "Warwickshire", + "WBK" => "West Berkshire", + "WDU" => "West Dunbartonshire", + "WFT" => "Waltham Forest", + "WGN" => "Wigan", + "WIL" => "Wiltshire", + "WKF" => "Wakefield", + "WLL" => "Walsall", + "WLN" => "West Lothian", + "WLS" => "Wales [Cymru GB-CYM]", + "WLV" => "Wolverhampton", + "WND" => "Wandsworth", + "WNM" => "Windsor and Maidenhead", + "WOK" => "Wokingham", + "WOR" => "Worcestershire", + "WRL" => "Wirral", + "WRT" => "Warrington", + "WRX" => "Wrexham [Wrecsam GB-WRC]", + "WSM" => "Westminster", + "WSX" => "West Sussex", + "YOR" => "York", + "ZET" => "Shetland Islands" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GD.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GD.php new file mode 100644 index 0000000..a9adc56 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GD.php @@ -0,0 +1,13 @@ + "Grenada", + "subdivisions" => [ + "01" => "Saint Andrew", + "02" => "Saint David", + "03" => "Saint George", + "04" => "Saint John", + "05" => "Saint Mark", + "06" => "Saint Patrick", + "10" => "Southern Grenadine Islands" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GE.php new file mode 100644 index 0000000..13a2c56 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GE.php @@ -0,0 +1,18 @@ + "Georgia", + "subdivisions" => [ + "AB" => "Abkhazia", + "AJ" => "Ajaria", + "GU" => "Guria", + "IM" => "Imereti", + "KA" => "K'akheti", + "KK" => "Kvemo Kartli", + "MM" => "Mtskheta-Mtianeti", + "RL" => "Rach'a-Lechkhumi-Kvemo Svaneti", + "SJ" => "Samtskhe-Javakheti", + "SK" => "Shida Kartli", + "SZ" => "Samegrelo-Zemo Svaneti", + "TB" => "Tbilisi" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GF.php new file mode 100644 index 0000000..0c1ca47 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GF.php @@ -0,0 +1,6 @@ + "French Guiana", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GG.php new file mode 100644 index 0000000..7256a55 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GG.php @@ -0,0 +1,6 @@ + "Guernsey", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GH.php new file mode 100644 index 0000000..ed4c140 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GH.php @@ -0,0 +1,22 @@ + "Ghana", + "subdivisions" => [ + "AA" => "Greater Accra", + "AF" => "Ahafo", + "AH" => "Ashanti", + "BE" => "Bono East", + "BO" => "Bono", + "CP" => "Central", + "EP" => "Eastern", + "NE" => "North East", + "NP" => "Northern", + "OT" => "Oti", + "SV" => "Savannah", + "TV" => "Volta", + "UE" => "Upper East", + "UW" => "Upper West", + "WN" => "Western North", + "WP" => "Western" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GI.php new file mode 100644 index 0000000..420d142 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GI.php @@ -0,0 +1,6 @@ + "Gibraltar", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GL.php new file mode 100644 index 0000000..d5f1226 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GL.php @@ -0,0 +1,11 @@ + "Greenland", + "subdivisions" => [ + "AV" => "Avannaata Kommunia", + "KU" => "Kommune Kujalleq", + "QE" => "Qeqqata Kommunia", + "QT" => "Kommune Qeqertalik", + "SM" => "Kommuneqarfik Sermersooq" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GM.php new file mode 100644 index 0000000..00ca257 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GM.php @@ -0,0 +1,12 @@ + "Gambia", + "subdivisions" => [ + "B" => "Banjul", + "L" => "Lower River", + "M" => "Central River", + "N" => "North Bank", + "U" => "Upper River", + "W" => "Western" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GN.php new file mode 100644 index 0000000..8c8756b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GN.php @@ -0,0 +1,47 @@ + "Guinea", + "subdivisions" => [ + "B" => "Boké", + "BE" => "Beyla", + "BF" => "Boffa", + "BK" => "Boké", + "C" => "Conakry", + "CO" => "Coyah", + "D" => "Kindia", + "DB" => "Dabola", + "DI" => "Dinguiraye", + "DL" => "Dalaba", + "DU" => "Dubréka", + "F" => "Faranah", + "FA" => "Faranah", + "FO" => "Forécariah", + "FR" => "Fria", + "GA" => "Gaoual", + "GU" => "Guékédou", + "K" => "Kankan", + "KA" => "Kankan", + "KB" => "Koubia", + "KD" => "Kindia", + "KE" => "Kérouané", + "KN" => "Koundara", + "KO" => "Kouroussa", + "KS" => "Kissidougou", + "L" => "Labé", + "LA" => "Labé", + "LE" => "Lélouma", + "LO" => "Lola", + "M" => "Mamou", + "MC" => "Macenta", + "MD" => "Mandiana", + "ML" => "Mali", + "MM" => "Mamou", + "N" => "Nzérékoré", + "NZ" => "Nzérékoré", + "PI" => "Pita", + "SI" => "Siguiri", + "TE" => "Télimélé", + "TO" => "Tougué", + "YO" => "Yomou" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GP.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GP.php new file mode 100644 index 0000000..b4dc81b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GP.php @@ -0,0 +1,6 @@ + "Guadeloupe", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GQ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GQ.php new file mode 100644 index 0000000..a2020a0 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GQ.php @@ -0,0 +1,16 @@ + "Equatorial Guinea", + "subdivisions" => [ + "AN" => "Annobon", + "BN" => "Bioko Nord", + "BS" => "Bioko Sud", + "C" => "Região Continental", + "CS" => "Centro Sud", + "DJ" => "Djibloho", + "I" => "Região Insular", + "KN" => "Kié-Ntem", + "LI" => "Litoral", + "WN" => "Wele-Nzas" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GR.php new file mode 100644 index 0000000..5047a6b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GR.php @@ -0,0 +1,20 @@ + "Greece", + "subdivisions" => [ + "69" => "Ágion Óros", + "A" => "Anatolikí Makedonía kai Thráki", + "B" => "Kentrikí Makedonía", + "C" => "Dytikí Makedonía", + "D" => "Ípeiros", + "E" => "Thessalía", + "F" => "Ionía Nísia", + "G" => "Dytikí Elláda", + "H" => "Stereá Elláda", + "I" => "Attikí", + "J" => "Pelopónnisos", + "K" => "Vóreio Aigaío", + "L" => "Nótio Aigaío", + "M" => "Kríti" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GS.php new file mode 100644 index 0000000..39e0c35 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GS.php @@ -0,0 +1,6 @@ + "South Georgia and the South Sandwich Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GT.php new file mode 100644 index 0000000..deab276 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GT.php @@ -0,0 +1,28 @@ + "Guatemala", + "subdivisions" => [ + "AV" => "Alta Verapaz", + "BV" => "Baja Verapaz", + "CM" => "Chimaltenango", + "CQ" => "Chiquimula", + "ES" => "Escuintla", + "GU" => "Guatemala", + "HU" => "Huehuetenango", + "IZ" => "Izabal", + "JA" => "Jalapa", + "JU" => "Jutiapa", + "PE" => "Petén", + "PR" => "El Progreso", + "QC" => "Quiché", + "QZ" => "Quetzaltenango", + "RE" => "Retalhuleu", + "SA" => "Sacatepéquez", + "SM" => "San Marcos", + "SO" => "Sololá", + "SR" => "Santa Rosa", + "SU" => "Suchitepéquez", + "TO" => "Totonicapán", + "ZA" => "Zacapa" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GU.php new file mode 100644 index 0000000..f876507 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GU.php @@ -0,0 +1,6 @@ + "Guam", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GW.php new file mode 100644 index 0000000..52cd368 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GW.php @@ -0,0 +1,18 @@ + "Guinea-Bissau", + "subdivisions" => [ + "BA" => "Bafatá", + "BL" => "Bolama / Bijagós", + "BM" => "Biombo", + "BS" => "Bissau", + "CA" => "Cacheu", + "GA" => "Gabú", + "L" => "Leste", + "N" => "Norte", + "OI" => "Oio", + "QU" => "Quinara", + "S" => "Sul", + "TO" => "Tombali" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/GY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/GY.php new file mode 100644 index 0000000..92de694 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/GY.php @@ -0,0 +1,16 @@ + "Guyana", + "subdivisions" => [ + "BA" => "Barima-Waini", + "CU" => "Cuyuni-Mazaruni", + "DE" => "Demerara-Mahaica", + "EB" => "East Berbice-Corentyne", + "ES" => "Essequibo Islands-West Demerara", + "MA" => "Mahaica-Berbice", + "PM" => "Pomeroon-Supenaam", + "PT" => "Potaro-Siparuni", + "UD" => "Upper Demerara-Berbice", + "UT" => "Upper Takutu-Upper Essequibo" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/HK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/HK.php new file mode 100644 index 0000000..006f197 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/HK.php @@ -0,0 +1,6 @@ + "Hong Kong", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/HM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/HM.php new file mode 100644 index 0000000..53a55d8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/HM.php @@ -0,0 +1,6 @@ + "Heard Island and McDonald Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/HN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/HN.php new file mode 100644 index 0000000..26eb361 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/HN.php @@ -0,0 +1,24 @@ + "Honduras", + "subdivisions" => [ + "AT" => "Atlántida", + "CH" => "Choluteca", + "CL" => "Colón", + "CM" => "Comayagua", + "CP" => "Copán", + "CR" => "Cortés", + "EP" => "El Paraíso", + "FM" => "Francisco Morazán", + "GD" => "Gracias a Dios", + "IB" => "Islas de la Bahía", + "IN" => "Intibucá", + "LE" => "Lempira", + "LP" => "La Paz", + "OC" => "Ocotepeque", + "OL" => "Olancho", + "SB" => "Santa Bárbara", + "VA" => "Valle", + "YO" => "Yoro" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/HR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/HR.php new file mode 100644 index 0000000..67122d1 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/HR.php @@ -0,0 +1,27 @@ + "Croatia", + "subdivisions" => [ + "01" => "Zagrebačka županija", + "02" => "Krapinsko-zagorska županija", + "03" => "Sisačko-moslavačka županija", + "04" => "Karlovačka županija", + "05" => "Varaždinska županija", + "06" => "Koprivničko-križevačka županija", + "07" => "Bjelovarsko-bilogorska županija", + "08" => "Primorsko-goranska županija", + "09" => "Ličko-senjska županija", + "10" => "Virovitičko-podravska županija", + "11" => "Požeško-slavonska županija", + "12" => "Brodsko-posavska županija", + "13" => "Zadarska županija", + "14" => "Osječko-baranjska županija", + "15" => "Šibensko-kninska županija", + "16" => "Vukovarsko-srijemska županija", + "17" => "Splitsko-dalmatinska županija", + "18" => "Istarska županija", + "19" => "Dubrovačko-neretvanska županija", + "20" => "Međimurska županija", + "21" => "Grad Zagreb" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/HT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/HT.php new file mode 100644 index 0000000..5b5750d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/HT.php @@ -0,0 +1,16 @@ + "Haiti", + "subdivisions" => [ + "AR" => "Artibonite", + "CE" => "Centre", + "GA" => "Grandans", + "ND" => "Nord", + "NE" => "Nord-Est", + "NI" => "Nip", + "NO" => "Nord-Ouest", + "OU" => "Lwès", + "SD" => "Sid", + "SE" => "Sidès" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/HU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/HU.php new file mode 100644 index 0000000..356df38 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/HU.php @@ -0,0 +1,49 @@ + "Hungary", + "subdivisions" => [ + "BA" => "Baranya", + "BC" => "Békéscsaba", + "BE" => "Békés", + "BK" => "Bács-Kiskun", + "BU" => "Budapest", + "BZ" => "Borsod-Abaúj-Zemplén", + "CS" => "Csongrád", + "DE" => "Debrecen", + "DU" => "Dunaújváros", + "EG" => "Eger", + "ER" => "Érd", + "FE" => "Fejér", + "GS" => "Győr-Moson-Sopron", + "GY" => "Győr", + "HB" => "Hajdú-Bihar", + "HE" => "Heves", + "HV" => "Hódmezővásárhely", + "JN" => "Jász-Nagykun-Szolnok", + "KE" => "Komárom-Esztergom", + "KM" => "Kecskemét", + "KV" => "Kaposvár", + "MI" => "Miskolc", + "NK" => "Nagykanizsa", + "NO" => "Nógrád", + "NY" => "Nyíregyháza", + "PE" => "Pest", + "PS" => "Pécs", + "SD" => "Szeged", + "SF" => "Székesfehérvár", + "SH" => "Szombathely", + "SK" => "Szolnok", + "SN" => "Sopron", + "SO" => "Somogy", + "SS" => "Szekszárd", + "ST" => "Salgótarján", + "SZ" => "Szabolcs-Szatmár-Bereg", + "TB" => "Tatabánya", + "TO" => "Tolna", + "VA" => "Vas", + "VE" => "Veszprém", + "VM" => "Veszprém", + "ZA" => "Zala", + "ZE" => "Zalaegerszeg" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ID.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ID.php new file mode 100644 index 0000000..15a057c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ID.php @@ -0,0 +1,47 @@ + "Indonesia", + "subdivisions" => [ + "AC" => "Aceh", + "BA" => "Bali", + "BB" => "Kepulauan Bangka Belitung", + "BE" => "Bengkulu", + "BT" => "Banten", + "GO" => "Gorontalo", + "JA" => "Jambi", + "JB" => "Jawa Barat", + "JI" => "Jawa Timur", + "JK" => "Jakarta Raya", + "JT" => "Jawa Tengah", + "JW" => "Jawa", + "KA" => "Kalimantan", + "KB" => "Kalimantan Barat", + "KI" => "Kalimantan Timur", + "KR" => "Kepulauan Riau", + "KS" => "Kalimantan Selatan", + "KT" => "Kalimantan Tengah", + "KU" => "Kalimantan Utara", + "LA" => "Lampung", + "MA" => "Maluku", + "ML" => "Maluku", + "MU" => "Maluku Utara", + "NB" => "Nusa Tenggara Barat", + "NT" => "Nusa Tenggara Timur", + "NU" => "Nusa Tenggara", + "PA" => "Papua", + "PB" => "Papua Barat", + "PP" => "Papua", + "RI" => "Riau", + "SA" => "Sulawesi Utara", + "SB" => "Sumatera Barat", + "SG" => "Sulawesi Tenggara", + "SL" => "Sulawesi", + "SM" => "Sumatera", + "SN" => "Sulawesi Selatan", + "SR" => "Sulawesi Barat", + "SS" => "Sumatera Selatan", + "ST" => "Sulawesi Tengah", + "SU" => "Sumatera Utara", + "YO" => "Yogyakarta" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IE.php new file mode 100644 index 0000000..097ee1f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IE.php @@ -0,0 +1,36 @@ + "Ireland", + "subdivisions" => [ + "C" => "Connaught", + "CE" => "Clare", + "CN" => "Cavan", + "CO" => "Cork", + "CW" => "Carlow", + "D" => "Dublin", + "DL" => "Donegal", + "G" => "Galway", + "KE" => "Kildare", + "KK" => "Kilkenny", + "KY" => "Kerry", + "L" => "Leinster", + "LD" => "Longford", + "LH" => "Louth", + "LK" => "Limerick", + "LM" => "Leitrim", + "LS" => "Laois", + "M" => "Munster", + "MH" => "Meath", + "MN" => "Monaghan", + "MO" => "Mayo", + "OY" => "Offaly", + "RN" => "Roscommon", + "SO" => "Sligo", + "TA" => "Tipperary", + "U" => "Ulster", + "WD" => "Waterford", + "WH" => "Westmeath", + "WW" => "Wicklow", + "WX" => "Wexford" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IL.php new file mode 100644 index 0000000..a242ef3 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IL.php @@ -0,0 +1,12 @@ + "Israel", + "subdivisions" => [ + "D" => "Al Janūbī", + "HA" => "H̱efa", + "JM" => "Al Quds", + "M" => "Al Awsaţ", + "TA" => "Tall Abīb", + "Z" => "Ash Shamālī" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IM.php new file mode 100644 index 0000000..4697912 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IM.php @@ -0,0 +1,6 @@ + "Isle of Man", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IN.php new file mode 100644 index 0000000..b4c6b90 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IN.php @@ -0,0 +1,42 @@ + "India", + "subdivisions" => [ + "AN" => "Andaman and Nicobar Islands", + "AP" => "Andhra Pradesh", + "AR" => "Arunāchal Pradesh", + "AS" => "Assam", + "BR" => "Bihār", + "CH" => "Chandīgarh", + "CT" => "Chhattīsgarh", + "DH" => "Dādra and Nagar Haveli and Damān and Diu", + "DL" => "Delhi", + "GA" => "Goa", + "GJ" => "Gujarāt", + "HP" => "Himāchal Pradesh", + "HR" => "Haryāna", + "JH" => "Jhārkhand", + "JK" => "Jammu and Kashmīr", + "KA" => "Karnātaka", + "KL" => "Kerala", + "LA" => "Ladākh", + "LD" => "Lakshadweep", + "MH" => "Mahārāshtra", + "ML" => "Meghālaya", + "MN" => "Manipur", + "MP" => "Madhya Pradesh", + "MZ" => "Mizoram", + "NL" => "Nāgāland", + "OR" => "Odisha", + "PB" => "Punjab", + "PY" => "Puducherry", + "RJ" => "Rājasthān", + "SK" => "Sikkim", + "TG" => "Telangāna", + "TN" => "Tamil Nādu", + "TR" => "Tripura", + "UP" => "Uttar Pradesh", + "UT" => "Uttarākhand", + "WB" => "West Bengal" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IO.php new file mode 100644 index 0000000..e453119 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IO.php @@ -0,0 +1,6 @@ + "British Indian Ocean Territory", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IQ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IQ.php new file mode 100644 index 0000000..c7bf486 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IQ.php @@ -0,0 +1,24 @@ + "Iraq", + "subdivisions" => [ + "AN" => "Al Anbār", + "AR" => "Arbīl", + "BA" => "Al Başrah", + "BB" => "Bābil", + "BG" => "Baghdād", + "DA" => "Dahūk", + "DI" => "Diyālá", + "DQ" => "Dhī Qār", + "KA" => "Karbalā’", + "KI" => "Kirkūk", + "MA" => "Maysān", + "MU" => "Al Muthanná", + "NA" => "An Najaf", + "NI" => "Nīnawá", + "QA" => "Al Qādisīyah", + "SD" => "Şalāḩ ad Dīn", + "SU" => "As Sulaymānīyah", + "WA" => "Wāsiţ" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IR.php new file mode 100644 index 0000000..ec394e0 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IR.php @@ -0,0 +1,37 @@ + "Iran, Islamic Republic of", + "subdivisions" => [ + "00" => "Markazī", + "01" => "Gīlān", + "02" => "Māzandarān", + "03" => "Āz̄ārbāyjān-e Shārqī", + "04" => "Āz̄ārbāyjān-e Ghārbī", + "05" => "Kermānshāh", + "06" => "Khūzestān", + "07" => "Fārs", + "08" => "Kermān", + "09" => "Khorāsān-e Raẕavī", + "10" => "Eşfahān", + "11" => "Sīstān va Balūchestān", + "12" => "Kordestān", + "13" => "Hamadān", + "14" => "Chahār Maḩāl va Bakhtīārī", + "15" => "Lorestān", + "16" => "Īlām", + "17" => "Kohgīlūyeh va Bowyer Aḩmad", + "18" => "Būshehr", + "19" => "Zanjān", + "20" => "Semnān", + "21" => "Yazd", + "22" => "Hormozgān", + "23" => "Tehrān", + "24" => "Ardabīl", + "25" => "Qom", + "26" => "Qazvīn", + "27" => "Golestān", + "28" => "Khorāsān-e Shomālī", + "29" => "Khorāsān-e Jonūbī", + "30" => "Alborz" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IS.php new file mode 100644 index 0000000..0cbceab --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IS.php @@ -0,0 +1,86 @@ + "Iceland", + "subdivisions" => [ + "1" => "Höfuðborgarsvæði", + "2" => "Suðurnes", + "3" => "Vesturland", + "4" => "Vestfirðir", + "5" => "Norðurland vestra", + "6" => "Norðurland eystra", + "7" => "Austurland", + "8" => "Suðurland", + "AKH" => "Akrahreppur", + "AKN" => "Akraneskaupstaður", + "AKU" => "Akureyrarbær", + "ARN" => "Árneshreppur", + "ASA" => "Ásahreppur", + "BFJ" => "Borgarfjarðarhreppur", + "BLA" => "Bláskógabyggð", + "BLO" => "Blönduósbær", + "BOG" => "Borgarbyggð", + "BOL" => "Bolungarvíkurkaupstaður", + "DAB" => "Dalabyggð", + "DAV" => "Dalvíkurbyggð", + "DJU" => "Djúpavogshreppur", + "EOM" => "Eyja- og Miklaholtshreppur", + "EYF" => "Eyjafjarðarsveit", + "FJD" => "Fjarðabyggð", + "FJL" => "Fjallabyggð", + "FLA" => "Flóahreppur", + "FLD" => "Fljótsdalshérað", + "FLR" => "Fljótsdalshreppur", + "GAR" => "Garðabær", + "GOG" => "Grímsnes- og Grafningshreppur", + "GRN" => "Grindavíkurbær", + "GRU" => "Grundarfjarðarbær", + "GRY" => "Grýtubakkahreppur", + "HAF" => "Hafnarfjarðarkaupstaður", + "HEL" => "Helgafellssveit", + "HRG" => "Hörgársveit", + "HRU" => "Hrunamannahreppur", + "HUT" => "Húnavatnshreppur", + "HUV" => "Húnaþing vestra", + "HVA" => "Hvalfjarðarsveit", + "HVE" => "Hveragerðisbær", + "ISA" => "Ísafjarðarbær", + "KAL" => "Kaldrananeshreppur", + "KJO" => "Kjósarhreppur", + "KOP" => "Kópavogsbær", + "LAN" => "Langanesbyggð", + "MOS" => "Mosfellsbær", + "MYR" => "Mýrdalshreppur", + "NOR" => "Norðurþing", + "RGE" => "Rangárþing eystra", + "RGY" => "Rangárþing ytra", + "RHH" => "Reykhólahreppur", + "RKN" => "Reykjanesbær", + "RKV" => "Reykjavíkurborg", + "SBH" => "Svalbarðshreppur", + "SBT" => "Svalbarðsstrandarhreppur", + "SDN" => "Suðurnesjabær", + "SDV" => "Súðavíkurhreppur", + "SEL" => "Seltjarnarnesbær", + "SEY" => "Seyðisfjarðarkaupstaður", + "SFA" => "Sveitarfélagið Árborg", + "SHF" => "Sveitarfélagið Hornafjörður", + "SKF" => "Skaftárhreppur", + "SKG" => "Skagabyggð", + "SKO" => "Skorradalshreppur", + "SKU" => "Skútustaðahreppur", + "SNF" => "Snæfellsbær", + "SOG" => "Skeiða- og Gnúpverjahreppur", + "SOL" => "Sveitarfélagið Ölfus", + "SSF" => "Sveitarfélagið Skagafjörður", + "SSS" => "Sveitarfélagið Skagaströnd", + "STR" => "Strandabyggð", + "STY" => "Stykkishólmsbær", + "SVG" => "Sveitarfélagið Vogar", + "TAL" => "Tálknafjarðarhreppur", + "THG" => "Þingeyjarsveit", + "TJO" => "Tjörneshreppur", + "VEM" => "Vestmannaeyjabær", + "VER" => "Vesturbyggð", + "VOP" => "Vopnafjarðarhreppur" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/IT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/IT.php new file mode 100644 index 0000000..3e48f37 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/IT.php @@ -0,0 +1,132 @@ + "Italy", + "subdivisions" => [ + "21" => "Piemonte", + "23" => "Val d'Aoste", + "25" => "Lombardia", + "32" => "Trentino-Alto Adige", + "34" => "Veneto", + "36" => "Friuli Venezia Giulia", + "42" => "Liguria", + "45" => "Emilia-Romagna", + "52" => "Toscana", + "55" => "Umbria", + "57" => "Marche", + "62" => "Lazio", + "65" => "Abruzzo", + "67" => "Molise", + "72" => "Campania", + "75" => "Puglia", + "77" => "Basilicata", + "78" => "Calabria", + "82" => "Sicilia", + "88" => "Sardegna", + "AG" => "Agrigento", + "AL" => "Alessandria", + "AN" => "Ancona", + "AP" => "Ascoli Piceno", + "AQ" => "L'Aquila", + "AR" => "Arezzo", + "AT" => "Asti", + "AV" => "Avellino", + "BA" => "Bari", + "BG" => "Bergamo", + "BI" => "Biella", + "BL" => "Belluno", + "BN" => "Benevento", + "BO" => "Bologna", + "BR" => "Brindisi", + "BS" => "Brescia", + "BT" => "Barletta-Andria-Trani", + "BZ" => "Bolzano", + "CA" => "Cagliari", + "CB" => "Campobasso", + "CE" => "Caserta", + "CH" => "Chieti", + "CL" => "Caltanissetta", + "CN" => "Cuneo", + "CO" => "Como", + "CR" => "Cremona", + "CS" => "Cosenza", + "CT" => "Catania", + "CZ" => "Catanzaro", + "EN" => "Enna", + "FC" => "Forlì-Cesena", + "FE" => "Ferrara", + "FG" => "Foggia", + "FI" => "Firenze", + "FM" => "Fermo", + "FR" => "Frosinone", + "GE" => "Genova", + "GO" => "Gorizia", + "GR" => "Grosseto", + "IM" => "Imperia", + "IS" => "Isernia", + "KR" => "Crotone", + "LC" => "Lecco", + "LE" => "Lecce", + "LI" => "Livorno", + "LO" => "Lodi", + "LT" => "Latina", + "LU" => "Lucca", + "MB" => "Monza e Brianza", + "MC" => "Macerata", + "ME" => "Messina", + "MI" => "Milano", + "MN" => "Mantova", + "MO" => "Modena", + "MS" => "Massa-Carrara", + "MT" => "Matera", + "NA" => "Napoli", + "NO" => "Novara", + "NU" => "Nuoro", + "OR" => "Oristano", + "PA" => "Palermo", + "PC" => "Piacenza", + "PD" => "Padova", + "PE" => "Pescara", + "PG" => "Perugia", + "PI" => "Pisa", + "PN" => "Pordenone", + "PO" => "Prato", + "PR" => "Parma", + "PT" => "Pistoia", + "PU" => "Pesaro e Urbino", + "PV" => "Pavia", + "PZ" => "Potenza", + "RA" => "Ravenna", + "RC" => "Reggio Calabria", + "RE" => "Reggio Emilia", + "RG" => "Ragusa", + "RI" => "Rieti", + "RM" => "Roma", + "RN" => "Rimini", + "RO" => "Rovigo", + "SA" => "Salerno", + "SI" => "Siena", + "SO" => "Sondrio", + "SP" => "La Spezia", + "SR" => "Siracusa", + "SS" => "Sassari", + "SU" => "Sud Sardegna", + "SV" => "Savona", + "TA" => "Taranto", + "TE" => "Teramo", + "TN" => "Trento", + "TO" => "Torino", + "TP" => "Trapani", + "TR" => "Terni", + "TS" => "Trieste", + "TV" => "Treviso", + "UD" => "Udine", + "VA" => "Varese", + "VB" => "Verbano-Cusio-Ossola", + "VC" => "Vercelli", + "VE" => "Venezia", + "VI" => "Vicenza", + "VR" => "Verona", + "VT" => "Viterbo", + "VV" => "Vibo Valentia" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/JE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/JE.php new file mode 100644 index 0000000..b32f92e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/JE.php @@ -0,0 +1,6 @@ + "Jersey", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/JM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/JM.php new file mode 100644 index 0000000..1da6b7f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/JM.php @@ -0,0 +1,20 @@ + "Jamaica", + "subdivisions" => [ + "01" => "Kingston", + "02" => "Saint Andrew", + "03" => "Saint Thomas", + "04" => "Portland", + "05" => "Saint Mary", + "06" => "Saint Ann", + "07" => "Trelawny", + "08" => "Saint James", + "09" => "Hanover", + "10" => "Westmoreland", + "11" => "Saint Elizabeth", + "12" => "Manchester", + "13" => "Clarendon", + "14" => "Saint Catherine" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/JO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/JO.php new file mode 100644 index 0000000..0e5f151 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/JO.php @@ -0,0 +1,18 @@ + "Jordan", + "subdivisions" => [ + "AJ" => "‘Ajlūn", + "AM" => "Al ‘A̅şimah", + "AQ" => "Al ‘Aqabah", + "AT" => "Aţ Ţafīlah", + "AZ" => "Az Zarqā’", + "BA" => "Al Balqā’", + "IR" => "Irbid", + "JA" => "Jarash", + "KA" => "Al Karak", + "MA" => "Al Mafraq", + "MD" => "Mādabā", + "MN" => "Ma‘ān" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/JP.php b/cacme/vendor/workerman/validation/data/iso_3166-2/JP.php new file mode 100644 index 0000000..e79bd76 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/JP.php @@ -0,0 +1,53 @@ + "Japan", + "subdivisions" => [ + "01" => "Hokkaido", + "02" => "Aomori", + "03" => "Iwate", + "04" => "Miyagi", + "05" => "Akita", + "06" => "Yamagata", + "07" => "Fukushima", + "08" => "Ibaraki", + "09" => "Tochigi", + "10" => "Gunma", + "11" => "Saitama", + "12" => "Chiba", + "13" => "Tokyo", + "14" => "Kanagawa", + "15" => "Niigata", + "16" => "Toyama", + "17" => "Ishikawa", + "18" => "Fukui", + "19" => "Yamanashi", + "20" => "Nagano", + "21" => "Gifu", + "22" => "Shizuoka", + "23" => "Aichi", + "24" => "Mie", + "25" => "Shiga", + "26" => "Kyoto", + "27" => "Osaka", + "28" => "Hyogo", + "29" => "Nara", + "30" => "Wakayama", + "31" => "Tottori", + "32" => "Shimane", + "33" => "Okayama", + "34" => "Hiroshima", + "35" => "Yamaguchi", + "36" => "Tokushima", + "37" => "Kagawa", + "38" => "Ehime", + "39" => "Kochi", + "40" => "Fukuoka", + "41" => "Saga", + "42" => "Nagasaki", + "43" => "Kumamoto", + "44" => "Oita", + "45" => "Miyazaki", + "46" => "Kagoshima", + "47" => "Okinawa" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KE.php new file mode 100644 index 0000000..5684949 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KE.php @@ -0,0 +1,53 @@ + "Kenya", + "subdivisions" => [ + "01" => "Baringo", + "02" => "Bomet", + "03" => "Bungoma", + "04" => "Busia", + "05" => "Elgeyo/Marakwet", + "06" => "Embu", + "07" => "Garissa", + "08" => "Homa Bay", + "09" => "Isiolo", + "10" => "Kajiado", + "11" => "Kakamega", + "12" => "Kericho", + "13" => "Kiambu", + "14" => "Kilifi", + "15" => "Kirinyaga", + "16" => "Kisii", + "17" => "Kisumu", + "18" => "Kitui", + "19" => "Kwale", + "20" => "Laikipia", + "21" => "Lamu", + "22" => "Machakos", + "23" => "Makueni", + "24" => "Mandera", + "25" => "Marsabit", + "26" => "Meru", + "27" => "Migori", + "28" => "Mombasa", + "29" => "Murang'a", + "30" => "Nairobi City", + "31" => "Nakuru", + "32" => "Nandi", + "33" => "Narok", + "34" => "Nyamira", + "35" => "Nyandarua", + "36" => "Nyeri", + "37" => "Samburu", + "38" => "Siaya", + "39" => "Taita/Taveta", + "40" => "Tana River", + "41" => "Tharaka-Nithi", + "42" => "Trans Nzoia", + "43" => "Turkana", + "44" => "Uasin Gishu", + "45" => "Vihiga", + "46" => "Wajir", + "47" => "West Pokot" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KG.php new file mode 100644 index 0000000..21b4615 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KG.php @@ -0,0 +1,15 @@ + "Kyrgyzstan", + "subdivisions" => [ + "B" => "Batken", + "C" => "Chuyskaya oblast'", + "GB" => "Bishkek Shaary", + "GO" => "Gorod Osh", + "J" => "Dzhalal-Abadskaya oblast'", + "N" => "Naryn", + "O" => "Osh", + "T" => "Talas", + "Y" => "Issyk-Kul'skaja oblast'" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KH.php new file mode 100644 index 0000000..f7399bc --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KH.php @@ -0,0 +1,31 @@ + "Cambodia", + "subdivisions" => [ + "1" => "Banteay Mean Choăy", + "10" => "Kracheh", + "11" => "Mondol Kiri", + "12" => "Phnom Penh", + "13" => "Preah Vihear", + "14" => "Prey Veaeng", + "15" => "Pousaat", + "16" => "Rotanak Kiri", + "17" => "Siem Reab", + "18" => "Preah Sihanouk", + "19" => "Stoĕng Trêng", + "2" => "Baat Dambang", + "20" => "Svaay Rieng", + "21" => "Taakaev", + "22" => "Otdar Mean Chey", + "23" => "Kaeb", + "24" => "Pailin", + "25" => "Tbong Khmum", + "3" => "Kampong Chaam", + "4" => "Kampong Chhnang", + "5" => "Kampong Spueu", + "6" => "Kampong Thum", + "7" => "Kampot", + "8" => "Kandaal", + "9" => "Kaoh Kong" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KI.php new file mode 100644 index 0000000..889715e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KI.php @@ -0,0 +1,9 @@ + "Kiribati", + "subdivisions" => [ + "G" => "Gilbert Islands", + "L" => "Line Islands", + "P" => "Phoenix Islands" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KM.php new file mode 100644 index 0000000..5d648e1 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KM.php @@ -0,0 +1,9 @@ + "Comoros", + "subdivisions" => [ + "A" => "Andjouân", + "G" => "Andjazîdja", + "M" => "Mohéli" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KN.php new file mode 100644 index 0000000..4d6f8e4 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KN.php @@ -0,0 +1,22 @@ + "Saint Kitts and Nevis", + "subdivisions" => [ + "01" => "Christ Church Nichola Town", + "02" => "Saint Anne Sandy Point", + "03" => "Saint George Basseterre", + "04" => "Saint George Gingerland", + "05" => "Saint James Windward", + "06" => "Saint John Capisterre", + "07" => "Saint John Figtree", + "08" => "Saint Mary Cayon", + "09" => "Saint Paul Capisterre", + "10" => "Saint Paul Charlestown", + "11" => "Saint Peter Basseterre", + "12" => "Saint Thomas Lowland", + "13" => "Saint Thomas Middle Island", + "15" => "Trinity Palmetto Point", + "K" => "Saint Kitts", + "N" => "Nevis" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KP.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KP.php new file mode 100644 index 0000000..9a179ac --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KP.php @@ -0,0 +1,18 @@ + "Korea, Democratic People's Republic of", + "subdivisions" => [ + "01" => "P'yǒngyang", + "02" => "P'yǒngan-namdo", + "03" => "P'yǒngan-bukto", + "04" => "Chagang-do", + "05" => "Hwanghae-namdo", + "06" => "Hwanghae-bukto", + "07" => "Kangweonto", + "08" => "Hamgyǒng-namdo", + "09" => "Hamgyǒng-bukto", + "10" => "Ryanggang-do", + "13" => "Raseon", + "14" => "Nampho" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KR.php new file mode 100644 index 0000000..10c621e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KR.php @@ -0,0 +1,23 @@ + "Korea, Republic of", + "subdivisions" => [ + "11" => "Seoul-teukbyeolsi", + "26" => "Busan-gwangyeoksi", + "27" => "Daegu-gwangyeoksi", + "28" => "Incheon-gwangyeoksi", + "29" => "Gwangju-gwangyeoksi", + "30" => "Daejeon-gwangyeoksi", + "31" => "Ulsan-gwangyeoksi", + "41" => "Gyeonggi-do", + "42" => "Gangwon-do", + "43" => "Chungcheongbuk-do", + "44" => "Chungcheongnam-do", + "45" => "Jeollabuk-do", + "46" => "Jeollanam-do", + "47" => "Gyeongsangbuk-do", + "48" => "Gyeongsangnam-do", + "49" => "Jeju-teukbyeoljachido", + "50" => "Sejong" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KW.php new file mode 100644 index 0000000..0c37a80 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KW.php @@ -0,0 +1,12 @@ + "Kuwait", + "subdivisions" => [ + "AH" => "Al Aḩmadī", + "FA" => "Al Farwānīyah", + "HA" => "Ḩawallī", + "JA" => "Al Jahrā’", + "KU" => "Al ‘Āşimah", + "MU" => "Mubārak al Kabīr" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KY.php new file mode 100644 index 0000000..65d14bf --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KY.php @@ -0,0 +1,6 @@ + "Cayman Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/KZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/KZ.php new file mode 100644 index 0000000..f0b64f9 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/KZ.php @@ -0,0 +1,23 @@ + "Kazakhstan", + "subdivisions" => [ + "AKM" => "Akmolinskaja oblast'", + "AKT" => "Aktjubinskaja oblast'", + "ALA" => "Almaty", + "ALM" => "Almatinskaja oblast'", + "AST" => "Nur-Sultan", + "ATY" => "Atyrauskaja oblast'", + "KAR" => "Karagandinskaja oblast'", + "KUS" => "Kostanajskaja oblast'", + "KZY" => "Kyzylordinskaja oblast'", + "MAN" => "Mangghystaū oblysy", + "PAV" => "Pavlodar oblysy", + "SEV" => "Severo-Kazahstanskaja oblast'", + "SHY" => "Shymkent", + "VOS" => "Shyghys Qazaqstan oblysy", + "YUZ" => "Turkestankaya oblast'", + "ZAP" => "Batys Qazaqstan oblysy", + "ZHA" => "Zhambyl oblysy" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LA.php new file mode 100644 index 0000000..9f59d2f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LA.php @@ -0,0 +1,24 @@ + "Lao People's Democratic Republic", + "subdivisions" => [ + "AT" => "Attapu", + "BK" => "Bokèo", + "BL" => "Bolikhamxai", + "CH" => "Champasak", + "HO" => "Houaphan", + "KH" => "Khammouan", + "LM" => "Louang Namtha", + "LP" => "Louangphabang", + "OU" => "Oudômxai", + "PH" => "Phôngsali", + "SL" => "Salavan", + "SV" => "Savannakhét", + "VI" => "Viangchan", + "VT" => "Viangchan", + "XA" => "Xaignabouli", + "XE" => "Xékong", + "XI" => "Xiangkhouang", + "XS" => "Xaisômboun" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LB.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LB.php new file mode 100644 index 0000000..6681d1e --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LB.php @@ -0,0 +1,14 @@ + "Lebanon", + "subdivisions" => [ + "AK" => "Aakkâr", + "AS" => "Ash Shimāl", + "BA" => "Bayrūt", + "BH" => "Baalbek-Hermel", + "BI" => "Al Biqā‘", + "JA" => "Al Janūb", + "JL" => "Jabal Lubnān", + "NA" => "An Nabaţīyah" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LC.php new file mode 100644 index 0000000..a03206b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LC.php @@ -0,0 +1,16 @@ + "Saint Lucia", + "subdivisions" => [ + "01" => "Anse la Raye", + "02" => "Castries", + "03" => "Choiseul", + "05" => "Dennery", + "06" => "Gros Islet", + "07" => "Laborie", + "08" => "Micoud", + "10" => "Soufrière", + "11" => "Vieux Fort", + "12" => "Canaries" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LI.php new file mode 100644 index 0000000..4d6a137 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LI.php @@ -0,0 +1,17 @@ + "Liechtenstein", + "subdivisions" => [ + "01" => "Balzers", + "02" => "Eschen", + "03" => "Gamprin", + "04" => "Mauren", + "05" => "Planken", + "06" => "Ruggell", + "07" => "Schaan", + "08" => "Schellenberg", + "09" => "Triesen", + "10" => "Triesenberg", + "11" => "Vaduz" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LK.php new file mode 100644 index 0000000..7da27ef --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LK.php @@ -0,0 +1,40 @@ + "Sri Lanka", + "subdivisions" => [ + "1" => "Western Province", + "11" => "Colombo", + "12" => "Gampaha", + "13" => "Kalutara", + "2" => "Central Province", + "21" => "Kandy", + "22" => "Matale", + "23" => "Nuwara Eliya", + "3" => "Southern Province", + "31" => "Galle", + "32" => "Matara", + "33" => "Hambantota", + "4" => "Northern Province", + "41" => "Jaffna", + "42" => "Kilinochchi", + "43" => "Mannar", + "44" => "Vavuniya", + "45" => "Mullaittivu", + "5" => "Eastern Province", + "51" => "Batticaloa", + "52" => "Ampara", + "53" => "Trincomalee", + "6" => "North Western Province", + "61" => "Kurunegala", + "62" => "Puttalam", + "7" => "North Central Province", + "71" => "Anuradhapura", + "72" => "Polonnaruwa", + "8" => "Uva Province", + "81" => "Badulla", + "82" => "Monaragala", + "9" => "Sabaragamuwa Province", + "91" => "Ratnapura", + "92" => "Kegalla" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LR.php new file mode 100644 index 0000000..8ed3d51 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LR.php @@ -0,0 +1,21 @@ + "Liberia", + "subdivisions" => [ + "BG" => "Bong", + "BM" => "Bomi", + "CM" => "Grand Cape Mount", + "GB" => "Grand Bassa", + "GG" => "Grand Gedeh", + "GK" => "Grand Kru", + "GP" => "Gbarpolu", + "LO" => "Lofa", + "MG" => "Margibi", + "MO" => "Montserrado", + "MY" => "Maryland", + "NI" => "Nimba", + "RG" => "River Gee", + "RI" => "River Cess", + "SI" => "Sinoe" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LS.php new file mode 100644 index 0000000..8d4a93c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LS.php @@ -0,0 +1,16 @@ + "Lesotho", + "subdivisions" => [ + "A" => "Maseru", + "B" => "Botha-Bothe", + "C" => "Leribe", + "D" => "Berea", + "E" => "Mafeteng", + "F" => "Mohale's Hoek", + "G" => "Quthing", + "H" => "Qacha's Nek", + "J" => "Mokhotlong", + "K" => "Thaba-Tseka" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LT.php new file mode 100644 index 0000000..c9ac5fd --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LT.php @@ -0,0 +1,76 @@ + "Lithuania", + "subdivisions" => [ + "01" => "Akmenė", + "02" => "Alytaus miestas", + "03" => "Alytus", + "04" => "Anykščiai", + "05" => "Birštono", + "06" => "Biržai", + "07" => "Druskininkai", + "08" => "Elektrėnai", + "09" => "Ignalina", + "10" => "Jonava", + "11" => "Joniškis", + "12" => "Jurbarkas", + "13" => "Kaišiadorys", + "14" => "Kalvarijos", + "15" => "Kauno miestas", + "16" => "Kaunas", + "17" => "Kazlų Rūdos", + "18" => "Kėdainiai", + "19" => "Kelmė", + "20" => "Klaipėdos miestas", + "21" => "Klaipėda", + "22" => "Kretinga", + "23" => "Kupiškis", + "24" => "Lazdijai", + "25" => "Marijampolė", + "26" => "Mažeikiai", + "27" => "Molėtai", + "28" => "Neringa", + "29" => "Pagėgiai", + "30" => "Pakruojis", + "31" => "Palangos miestas", + "32" => "Panevėžio miestas", + "33" => "Panevėžys", + "34" => "Pasvalys", + "35" => "Plungė", + "36" => "Prienai", + "37" => "Radviliškis", + "38" => "Raseiniai", + "39" => "Rietavo", + "40" => "Rokiškis", + "41" => "Šakiai", + "42" => "Šalčininkai", + "43" => "Šiaulių miestas", + "44" => "Šiauliai", + "45" => "Šilalė", + "46" => "Šilutė", + "47" => "Širvintos", + "48" => "Skuodas", + "49" => "Švenčionys", + "50" => "Tauragė", + "51" => "Telšiai", + "52" => "Trakai", + "53" => "Ukmergė", + "54" => "Utena", + "55" => "Varėna", + "56" => "Vilkaviškis", + "57" => "Vilniaus miestas", + "58" => "Vilnius", + "59" => "Visaginas", + "60" => "Zarasai", + "AL" => "Alytaus apskritis", + "KL" => "Klaipėdos apskritis", + "KU" => "Kauno apskritis", + "MR" => "Marijampolės apskritis", + "PN" => "Panevėžio apskritis", + "SA" => "Šiaulių apskritis", + "TA" => "Tauragės apskritis", + "TE" => "Telšių apskritis", + "UT" => "Utenos apskritis", + "VL" => "Vilniaus apskritis" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LU.php new file mode 100644 index 0000000..068916b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LU.php @@ -0,0 +1,18 @@ + "Luxembourg", + "subdivisions" => [ + "CA" => "Capellen", + "CL" => "Clerf", + "DI" => "Diekirch", + "EC" => "Echternach", + "ES" => "Esch an der Alzette", + "GR" => "Grevenmacher", + "LU" => "Luxembourg", + "ME" => "Mersch", + "RD" => "Redange", + "RM" => "Remich", + "VD" => "Veianen", + "WI" => "Wiltz" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LV.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LV.php new file mode 100644 index 0000000..b62d2ba --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LV.php @@ -0,0 +1,125 @@ + "Latvia", + "subdivisions" => [ + "001" => "Aglonas novads", + "002" => "Aizkraukles novads", + "003" => "Aizputes novads", + "004" => "Aknīstes novads", + "005" => "Alojas novads", + "006" => "Alsungas novads", + "007" => "Alūksnes novads", + "008" => "Amatas novads", + "009" => "Apes novads", + "010" => "Auces novads", + "011" => "Ādažu novads", + "012" => "Babītes novads", + "013" => "Baldones novads", + "014" => "Baltinavas novads", + "015" => "Balvu novads", + "016" => "Bauskas novads", + "017" => "Beverīnas novads", + "018" => "Brocēnu novads", + "019" => "Burtnieku novads", + "020" => "Carnikavas novads", + "021" => "Cesvaines novads", + "022" => "Cēsu novads", + "023" => "Ciblas novads", + "024" => "Dagdas novads", + "025" => "Daugavpils novads", + "026" => "Dobeles novads", + "027" => "Dundagas novads", + "028" => "Durbes novads", + "029" => "Engures novads", + "030" => "Ērgļu novads", + "031" => "Garkalnes novads", + "032" => "Grobiņas novads", + "033" => "Gulbenes novads", + "034" => "Iecavas novads", + "035" => "Ikšķiles novads", + "036" => "Ilūkstes novads", + "037" => "Inčukalna novads", + "038" => "Jaunjelgavas novads", + "039" => "Jaunpiebalgas novads", + "040" => "Jaunpils novads", + "041" => "Jelgavas novads", + "042" => "Jēkabpils novads", + "043" => "Kandavas novads", + "044" => "Kārsavas novads", + "045" => "Kocēnu novads", + "046" => "Kokneses novads", + "047" => "Krāslavas novads", + "048" => "Krimuldas novads", + "049" => "Krustpils novads", + "050" => "Kuldīgas novads", + "051" => "Ķeguma novads", + "052" => "Ķekavas novads", + "053" => "Lielvārdes novads", + "054" => "Limbažu novads", + "055" => "Līgatnes novads", + "056" => "Līvānu novads", + "057" => "Lubānas novads", + "058" => "Ludzas novads", + "059" => "Madonas novads", + "060" => "Mazsalacas novads", + "061" => "Mālpils novads", + "062" => "Mārupes novads", + "063" => "Mērsraga novads", + "064" => "Naukšēnu novads", + "065" => "Neretas novads", + "066" => "Nīcas novads", + "067" => "Ogres novads", + "068" => "Olaines novads", + "069" => "Ozolnieku novads", + "070" => "Pārgaujas novads", + "071" => "Pāvilostas novads", + "072" => "Pļaviņu novads", + "073" => "Preiļu novads", + "074" => "Priekules novads", + "075" => "Priekuļu novads", + "076" => "Raunas novads", + "077" => "Rēzeknes novads", + "078" => "Riebiņu novads", + "079" => "Rojas novads", + "080" => "Ropažu novads", + "081" => "Rucavas novads", + "082" => "Rugāju novads", + "083" => "Rundāles novads", + "084" => "Rūjienas novads", + "085" => "Salas novads", + "086" => "Salacgrīvas novads", + "087" => "Salaspils novads", + "088" => "Saldus novads", + "089" => "Saulkrastu novads", + "090" => "Sējas novads", + "091" => "Siguldas novads", + "092" => "Skrīveru novads", + "093" => "Skrundas novads", + "094" => "Smiltenes novads", + "095" => "Stopiņu novads", + "096" => "Strenču novads", + "097" => "Talsu novads", + "098" => "Tērvetes novads", + "099" => "Tukuma novads", + "100" => "Vaiņodes novads", + "101" => "Valkas novads", + "102" => "Varakļānu novads", + "103" => "Vārkavas novads", + "104" => "Vecpiebalgas novads", + "105" => "Vecumnieku novads", + "106" => "Ventspils novads", + "107" => "Viesītes novads", + "108" => "Viļakas novads", + "109" => "Viļānu novads", + "110" => "Zilupes novads", + "DGV" => "Daugavpils", + "JEL" => "Jelgava", + "JKB" => "Jēkabpils", + "JUR" => "Jūrmala", + "LPX" => "Liepāja", + "REZ" => "Rēzekne", + "RIX" => "Rīga", + "VEN" => "Ventspils", + "VMR" => "Valmiera" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/LY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/LY.php new file mode 100644 index 0000000..c1b5c49 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/LY.php @@ -0,0 +1,28 @@ + "Libya", + "subdivisions" => [ + "BA" => "Banghāzī", + "BU" => "Al Buţnān", + "DR" => "Darnah", + "GT" => "Ghāt", + "JA" => "Al Jabal al Akhḑar", + "JG" => "Al Jabal al Gharbī", + "JI" => "Al Jafārah", + "JU" => "Al Jufrah", + "KF" => "Al Kufrah", + "MB" => "Al Marqab", + "MI" => "Mişrātah", + "MJ" => "Al Marj", + "MQ" => "Murzuq", + "NL" => "Nālūt", + "NQ" => "An Nuqāţ al Khams", + "SB" => "Sabhā", + "SR" => "Surt", + "TB" => "Ţarābulus", + "WA" => "Al Wāḩāt", + "WD" => "Wādī al Ḩayāt", + "WS" => "Wādī ash Shāţi’", + "ZA" => "Az Zāwiyah" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MA.php new file mode 100644 index 0000000..29f65b8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MA.php @@ -0,0 +1,93 @@ + "Morocco", + "subdivisions" => [ + "01" => "Tanger-Tétouan-Al Hoceïma", + "02" => "L'Oriental", + "03" => "Fès-Meknès", + "04" => "Rabat-Salé-Kénitra", + "05" => "Béni Mellal-Khénifra", + "06" => "Casablanca-Settat", + "07" => "Marrakech-Safi", + "08" => "Drâa-Tafilalet", + "09" => "Souss-Massa", + "10" => "Guelmim-Oued Noun (EH-partial)", + "11" => "Laâyoune-Sakia El Hamra (EH-partial)", + "12" => "Dakhla-Oued Ed-Dahab (EH)", + "AGD" => "Agadir-Ida-Ou-Tanane", + "AOU" => "Aousserd (EH)", + "ASZ" => "Assa-Zag (EH-partial)", + "AZI" => "Azilal", + "BEM" => "Béni Mellal", + "BER" => "Berkane", + "BES" => "Benslimane", + "BOD" => "Boujdour (EH)", + "BOM" => "Boulemane", + "BRR" => "Berrechid", + "CAS" => "Casablanca", + "CHE" => "Chefchaouen", + "CHI" => "Chichaoua", + "CHT" => "Chtouka-Ait Baha", + "DRI" => "Driouch", + "ERR" => "Errachidia", + "ESI" => "Essaouira", + "ESM" => "Es-Semara (EH-partial)", + "FAH" => "Fahs-Anjra", + "FES" => "Fès", + "FIG" => "Figuig", + "FQH" => "Fquih Ben Salah", + "GUE" => "Guelmim", + "GUF" => "Guercif", + "HAJ" => "El Hajeb", + "HAO" => "Al Haouz", + "HOC" => "Al Hoceïma", + "IFR" => "Ifrane", + "INE" => "Inezgane-Ait Melloul", + "JDI" => "El Jadida", + "JRA" => "Jerada", + "KEN" => "Kénitra", + "KES" => "El Kelâa des Sraghna", + "KHE" => "Khémisset", + "KHN" => "Khénifra", + "KHO" => "Khouribga", + "LAA" => "Laâyoune (EH)", + "LAR" => "Larache", + "MAR" => "Marrakech", + "MDF" => "M’diq-Fnideq", + "MED" => "Médiouna", + "MEK" => "Meknès", + "MID" => "Midelt", + "MOH" => "Mohammadia", + "MOU" => "Moulay Yacoub", + "NAD" => "Nador", + "NOU" => "Nouaceur", + "OUA" => "Ouarzazate", + "OUD" => "Oued Ed-Dahab (EH)", + "OUJ" => "Oujda-Angad", + "OUZ" => "Ouezzane", + "RAB" => "Rabat", + "REH" => "Rehamna", + "SAF" => "Safi", + "SAL" => "Salé", + "SEF" => "Sefrou", + "SET" => "Settat", + "SIB" => "Sidi Bennour", + "SIF" => "Sidi Ifni", + "SIK" => "Sidi Kacem", + "SIL" => "Sidi Slimane", + "SKH" => "Skhirate-Témara", + "TAF" => "Tarfaya (EH-partial)", + "TAI" => "Taourirt", + "TAO" => "Taounate", + "TAR" => "Taroudannt", + "TAT" => "Tata", + "TAZ" => "Taza", + "TET" => "Tétouan", + "TIN" => "Tinghir", + "TIZ" => "Tiznit", + "TNG" => "Tanger-Assilah", + "TNT" => "Tan-Tan (EH-partial)", + "YUS" => "Youssoufia", + "ZAG" => "Zagora" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MC.php new file mode 100644 index 0000000..368bdc9 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MC.php @@ -0,0 +1,23 @@ + "Monaco", + "subdivisions" => [ + "CL" => "La Colle", + "CO" => "La Condamine", + "FO" => "Fontvieille", + "GA" => "La Gare", + "JE" => "Jardin Exotique", + "LA" => "Larvotto", + "MA" => "Malbousquet", + "MC" => "Monte-Carlo", + "MG" => "Moneghetti", + "MO" => "Monaco-Ville", + "MU" => "Moulins", + "PH" => "Port-Hercule", + "SD" => "Sainte-Dévote", + "SO" => "La Source", + "SP" => "Spélugues", + "SR" => "Saint-Roman", + "VR" => "Vallon de la Rousse" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MD.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MD.php new file mode 100644 index 0000000..a89dd89 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MD.php @@ -0,0 +1,43 @@ + "Moldova, Republic of", + "subdivisions" => [ + "AN" => "Anenii Noi", + "BA" => "Bălți", + "BD" => "Bender [Tighina]", + "BR" => "Briceni", + "BS" => "Basarabeasca", + "CA" => "Cahul", + "CL" => "Călărași", + "CM" => "Cimișlia", + "CR" => "Criuleni", + "CS" => "Căușeni", + "CT" => "Cantemir", + "CU" => "Chișinău", + "DO" => "Dondușeni", + "DR" => "Drochia", + "DU" => "Dubăsari", + "ED" => "Edineț", + "FA" => "Fălești", + "FL" => "Florești", + "GA" => "Găgăuzia, Unitatea teritorială autonomă (UTAG)", + "GL" => "Glodeni", + "HI" => "Hîncești", + "IA" => "Ialoveni", + "LE" => "Leova", + "NI" => "Nisporeni", + "OC" => "Ocnița", + "OR" => "Orhei", + "RE" => "Rezina", + "RI" => "Rîșcani", + "SD" => "Șoldănești", + "SI" => "Sîngerei", + "SN" => "Stînga Nistrului, unitatea teritorială din", + "SO" => "Soroca", + "ST" => "Strășeni", + "SV" => "Ștefan Vodă", + "TA" => "Taraclia", + "TE" => "Telenești", + "UN" => "Ungheni" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ME.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ME.php new file mode 100644 index 0000000..ae677f6 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ME.php @@ -0,0 +1,30 @@ + "Montenegro", + "subdivisions" => [ + "01" => "Andrijevica", + "02" => "Bar", + "03" => "Berane", + "04" => "Bijelo Polje", + "05" => "Budva", + "06" => "Cetinje", + "07" => "Danilovgrad", + "08" => "Herceg-Novi", + "09" => "Kolašin", + "10" => "Kotor", + "11" => "Mojkovac", + "12" => "Nikšić", + "13" => "Plav", + "14" => "Pljevlja", + "15" => "Plužine", + "16" => "Podgorica", + "17" => "Rožaje", + "18" => "Šavnik", + "19" => "Tivat", + "20" => "Ulcinj", + "21" => "Žabljak", + "22" => "Gusinje", + "23" => "Petnjica", + "24" => "Tuzi" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MF.php new file mode 100644 index 0000000..c1f2ede --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MF.php @@ -0,0 +1,6 @@ + "Saint Martin (French part)", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MG.php new file mode 100644 index 0000000..e25c1ed --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MG.php @@ -0,0 +1,12 @@ + "Madagascar", + "subdivisions" => [ + "A" => "Toamasina", + "D" => "Antsiranana", + "F" => "Fianarantsoa", + "M" => "Mahajanga", + "T" => "Antananarivo", + "U" => "Toliara" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MH.php new file mode 100644 index 0000000..fe920bf --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MH.php @@ -0,0 +1,32 @@ + "Marshall Islands", + "subdivisions" => [ + "ALK" => "Ailuk", + "ALL" => "Ailinglaplap", + "ARN" => "Arno", + "AUR" => "Aur", + "EBO" => "Ebon", + "ENI" => "Enewetak & Ujelang", + "JAB" => "Jabat", + "JAL" => "Jaluit", + "KIL" => "Bikini & Kili", + "KWA" => "Kwajalein", + "L" => "Ralik chain", + "LAE" => "Lae", + "LIB" => "Lib", + "LIK" => "Likiep", + "MAJ" => "Majuro", + "MAL" => "Maloelap", + "MEJ" => "Mejit", + "MIL" => "Mili", + "NMK" => "Namdrik", + "NMU" => "Namu", + "RON" => "Rongelap", + "T" => "Ratak chain", + "UJA" => "Ujae", + "UTI" => "Utrik", + "WTH" => "Wotho", + "WTJ" => "Wotje" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MK.php new file mode 100644 index 0000000..f93e22d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MK.php @@ -0,0 +1,86 @@ + "North Macedonia", + "subdivisions" => [ + "101" => "Veles", + "102" => "Gradsko", + "103" => "Demir Kapija", + "104" => "Kavadarci", + "105" => "Lozovo", + "106" => "Negotino", + "107" => "Rosoman", + "108" => "Sveti Nikole", + "109" => "Čaška", + "201" => "Berovo", + "202" => "Vinica", + "203" => "Delčevo", + "204" => "Zrnovci", + "205" => "Karbinci", + "206" => "Kočani", + "207" => "Makedonska Kamenica", + "208" => "Pehčevo", + "209" => "Probištip", + "210" => "Češinovo-Obleševo", + "211" => "Štip", + "301" => "Vevčani", + "303" => "Debar", + "304" => "Debrca", + "307" => "Kičevo", + "308" => "Makedonski Brod", + "310" => "Ohrid", + "311" => "Plasnica", + "312" => "Struga", + "313" => "Centar Župa", + "401" => "Bogdanci", + "402" => "Bosilovo", + "403" => "Valandovo", + "404" => "Vasilevo", + "405" => "Gevgelija", + "406" => "Dojran", + "407" => "Konče", + "408" => "Novo Selo", + "409" => "Radoviš", + "410" => "Strumica", + "501" => "Bitola", + "502" => "Demir Hisar", + "503" => "Dolneni", + "504" => "Krivogaštani", + "505" => "Kruševo", + "506" => "Mogila", + "507" => "Novaci", + "508" => "Prilep", + "509" => "Resen", + "601" => "Bogovinje", + "602" => "Brvenica", + "603" => "Vrapčište", + "604" => "Gostivar", + "605" => "Želino", + "606" => "Jegunovce", + "607" => "Mavrovo i Rostuše", + "608" => "Tearce", + "609" => "Tetovo", + "701" => "Kratovo", + "702" => "Kriva Palanka", + "703" => "Kumanovo", + "704" => "Lipkovo", + "705" => "Rankovce", + "706" => "Staro Nagoričane", + "801" => "Aerodrom †", + "802" => "Aračinovo", + "803" => "Butel †", + "804" => "Gazi Baba †", + "805" => "Gjorče Petrov †", + "806" => "Zelenikovo", + "807" => "Ilinden", + "808" => "Karpoš †", + "809" => "Kisela Voda †", + "810" => "Petrovec", + "811" => "Saraj †", + "812" => "Sopište", + "813" => "Studeničani", + "814" => "Centar †", + "815" => "Čair †", + "816" => "Čučer-Sandevo", + "817" => "Šuto Orizari †" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ML.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ML.php new file mode 100644 index 0000000..0c00f75 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ML.php @@ -0,0 +1,17 @@ + "Mali", + "subdivisions" => [ + "1" => "Kayes", + "10" => "Taoudénit", + "2" => "Koulikoro", + "3" => "Sikasso", + "4" => "Ségou", + "5" => "Mopti", + "6" => "Tombouctou", + "7" => "Gao", + "8" => "Kidal", + "9" => "Ménaka", + "BKO" => "Bamako" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MM.php new file mode 100644 index 0000000..ea051a0 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MM.php @@ -0,0 +1,21 @@ + "Myanmar", + "subdivisions" => [ + "01" => "Sagaing", + "02" => "Bago", + "03" => "Magway", + "04" => "Mandalay", + "05" => "Tanintharyi", + "06" => "Yangon", + "07" => "Ayeyarwady", + "11" => "Kachin", + "12" => "Kayah", + "13" => "Kayin", + "14" => "Chin", + "15" => "Mon", + "16" => "Rakhine", + "17" => "Shan", + "18" => "Nay Pyi Taw" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MN.php new file mode 100644 index 0000000..1656361 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MN.php @@ -0,0 +1,28 @@ + "Mongolia", + "subdivisions" => [ + "035" => "Orhon", + "037" => "Darhan uul", + "039" => "Hentiy", + "041" => "Hövsgöl", + "043" => "Hovd", + "046" => "Uvs", + "047" => "Töv", + "049" => "Selenge", + "051" => "Sühbaatar", + "053" => "Ömnögovĭ", + "055" => "Övörhangay", + "057" => "Dzavhan", + "059" => "Dundgovĭ", + "061" => "Dornod", + "063" => "Dornogovĭ", + "064" => "Govĭ-Sümber", + "065" => "Govĭ-Altay", + "067" => "Bulgan", + "069" => "Bayanhongor", + "071" => "Bayan-Ölgiy", + "073" => "Arhangay", + "1" => "Ulaanbaatar" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MO.php new file mode 100644 index 0000000..2e33840 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MO.php @@ -0,0 +1,6 @@ + "Macao", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MP.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MP.php new file mode 100644 index 0000000..41eecf2 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MP.php @@ -0,0 +1,6 @@ + "Northern Mariana Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MQ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MQ.php new file mode 100644 index 0000000..21c3335 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MQ.php @@ -0,0 +1,6 @@ + "Martinique", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MR.php new file mode 100644 index 0000000..8a0761b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MR.php @@ -0,0 +1,21 @@ + "Mauritania", + "subdivisions" => [ + "01" => "Hodh ech Chargui", + "02" => "Hodh el Gharbi", + "03" => "Assaba", + "04" => "Gorgol", + "05" => "Brakna", + "06" => "Trarza", + "07" => "Adrar", + "08" => "Dakhlet Nouâdhibou", + "09" => "Tagant", + "10" => "Guidimaka", + "11" => "Tiris Zemmour", + "12" => "Inchiri", + "13" => "Nouakchott Ouest", + "14" => "Nouakchott Nord", + "15" => "Nouakchott Sud" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MS.php new file mode 100644 index 0000000..245a80f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MS.php @@ -0,0 +1,6 @@ + "Montserrat", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MT.php new file mode 100644 index 0000000..bb2c2b8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MT.php @@ -0,0 +1,74 @@ + "Malta", + "subdivisions" => [ + "01" => "Attard", + "02" => "Balzan", + "03" => "Birgu", + "04" => "Birkirkara", + "05" => "Birżebbuġa", + "06" => "Bormla", + "07" => "Dingli", + "08" => "Fgura", + "09" => "Floriana", + "10" => "Fontana", + "11" => "Gudja", + "12" => "Gżira", + "13" => "Għajnsielem", + "14" => "Għarb", + "15" => "Għargħur", + "16" => "Għasri", + "17" => "Għaxaq", + "18" => "Ħamrun", + "19" => "Iklin", + "20" => "Isla", + "21" => "Kalkara", + "22" => "Kerċem", + "23" => "Kirkop", + "24" => "Lija", + "25" => "Luqa", + "26" => "Marsa", + "27" => "Marsaskala", + "28" => "Marsaxlokk", + "29" => "Mdina", + "30" => "Mellieħa", + "31" => "Mġarr", + "32" => "Mosta", + "33" => "Mqabba", + "34" => "Msida", + "35" => "Mtarfa", + "36" => "Munxar", + "37" => "Nadur", + "38" => "Naxxar", + "39" => "Paola", + "40" => "Pembroke", + "41" => "Pietà", + "42" => "Qala", + "43" => "Qormi", + "44" => "Qrendi", + "45" => "Rabat Gozo", + "46" => "Rabat Malta", + "47" => "Safi", + "48" => "Saint Julian's", + "49" => "Saint John", + "50" => "Saint Lawrence", + "51" => "Saint Paul's Bay", + "52" => "Sannat", + "53" => "Saint Lucia's", + "54" => "Santa Venera", + "55" => "Siġġiewi", + "56" => "Sliema", + "57" => "Swieqi", + "58" => "Ta' Xbiex", + "59" => "Tarxien", + "60" => "Valletta", + "61" => "Xagħra", + "62" => "Xewkija", + "63" => "Xgħajra", + "64" => "Żabbar", + "65" => "Żebbuġ Gozo", + "66" => "Żebbuġ Malta", + "67" => "Żejtun", + "68" => "Żurrieq" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MU.php new file mode 100644 index 0000000..289df29 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MU.php @@ -0,0 +1,18 @@ + "Mauritius", + "subdivisions" => [ + "AG" => "Agalega Islands", + "BL" => "Black River", + "CC" => "Cargados Carajos Shoals", + "FL" => "Flacq", + "GP" => "Grand Port", + "MO" => "Moka", + "PA" => "Pamplemousses", + "PL" => "Port Louis", + "PW" => "Plaines Wilhems", + "RO" => "Rodrigues Island", + "RR" => "Rivière du Rempart", + "SA" => "Savanne" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MV.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MV.php new file mode 100644 index 0000000..0426727 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MV.php @@ -0,0 +1,27 @@ + "Maldives", + "subdivisions" => [ + "00" => "South Ari Atoll", + "01" => "Addu City", + "02" => "North Ari Atoll", + "03" => "Faadhippolhu", + "04" => "Felidhu Atoll", + "05" => "Hahdhunmathi", + "07" => "North Thiladhunmathi", + "08" => "Kolhumadulu", + "12" => "Mulaku Atoll", + "13" => "North Maalhosmadulu", + "14" => "North Nilandhe Atoll", + "17" => "South Nilandhe Atoll", + "20" => "South Maalhosmadulu", + "23" => "South Thiladhunmathi", + "24" => "North Miladhunmadulu", + "25" => "South Miladhunmadulu", + "26" => "Male Atoll", + "27" => "North Huvadhu Atoll", + "28" => "South Huvadhu Atoll", + "29" => "Fuvammulah", + "MLE" => "Male" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MW.php new file mode 100644 index 0000000..9be5b7f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MW.php @@ -0,0 +1,37 @@ + "Malawi", + "subdivisions" => [ + "BA" => "Balaka", + "BL" => "Blantyre", + "C" => "Central Region", + "CK" => "Chikwawa", + "CR" => "Chiradzulu", + "CT" => "Chitipa", + "DE" => "Dedza", + "DO" => "Dowa", + "KR" => "Karonga", + "KS" => "Kasungu", + "LI" => "Lilongwe", + "LK" => "Likoma", + "MC" => "Mchinji", + "MG" => "Mangochi", + "MH" => "Machinga", + "MU" => "Mulanje", + "MW" => "Mwanza", + "MZ" => "Mzimba", + "N" => "Northern Region", + "NB" => "Nkhata Bay", + "NE" => "Neno", + "NI" => "Ntchisi", + "NK" => "Nkhotakota", + "NS" => "Nsanje", + "NU" => "Ntcheu", + "PH" => "Phalombe", + "RU" => "Rumphi", + "S" => "Southern Region", + "SA" => "Salima", + "TH" => "Thyolo", + "ZO" => "Zomba" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MX.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MX.php new file mode 100644 index 0000000..8b63b99 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MX.php @@ -0,0 +1,38 @@ + "Mexico", + "subdivisions" => [ + "AGU" => "Aguascalientes", + "BCN" => "Baja California", + "BCS" => "Baja California Sur", + "CAM" => "Campeche", + "CHH" => "Chihuahua", + "CHP" => "Chiapas", + "CMX" => "Ciudad de México", + "COA" => "Coahuila de Zaragoza", + "COL" => "Colima", + "DUR" => "Durango", + "GRO" => "Guerrero", + "GUA" => "Guanajuato", + "HID" => "Hidalgo", + "JAL" => "Jalisco", + "MEX" => "México", + "MIC" => "Michoacán de Ocampo", + "MOR" => "Morelos", + "NAY" => "Nayarit", + "NLE" => "Nuevo León", + "OAX" => "Oaxaca", + "PUE" => "Puebla", + "QUE" => "Querétaro", + "ROO" => "Quintana Roo", + "SIN" => "Sinaloa", + "SLP" => "San Luis Potosí", + "SON" => "Sonora", + "TAB" => "Tabasco", + "TAM" => "Tamaulipas", + "TLA" => "Tlaxcala", + "VER" => "Veracruz de Ignacio de la Llave", + "YUC" => "Yucatán", + "ZAC" => "Zacatecas" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MY.php new file mode 100644 index 0000000..9828884 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MY.php @@ -0,0 +1,22 @@ + "Malaysia", + "subdivisions" => [ + "01" => "Johor", + "02" => "Kedah", + "03" => "Kelantan", + "04" => "Melaka", + "05" => "Negeri Sembilan", + "06" => "Pahang", + "07" => "Pulau Pinang", + "08" => "Perak", + "09" => "Perlis", + "10" => "Selangor", + "11" => "Terengganu", + "12" => "Sabah", + "13" => "Sarawak", + "14" => "Wilayah Persekutuan Kuala Lumpur", + "15" => "Wilayah Persekutuan Labuan", + "16" => "Wilayah Persekutuan Putrajaya" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/MZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/MZ.php new file mode 100644 index 0000000..dfc9c35 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/MZ.php @@ -0,0 +1,17 @@ + "Mozambique", + "subdivisions" => [ + "A" => "Niassa", + "B" => "Manica", + "G" => "Gaza", + "I" => "Inhambane", + "L" => "Maputo", + "MPM" => "Maputo", + "N" => "Nampula", + "P" => "Cabo Delgado", + "Q" => "Zambézia", + "S" => "Sofala", + "T" => "Tete" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NA.php new file mode 100644 index 0000000..f3709ab --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NA.php @@ -0,0 +1,20 @@ + "Namibia", + "subdivisions" => [ + "CA" => "Zambezi", + "ER" => "Erongo", + "HA" => "Hardap", + "KA" => "//Karas", + "KE" => "Kavango East", + "KH" => "Khomas", + "KU" => "Kunene", + "KW" => "Kavango West", + "OD" => "Otjozondjupa", + "OH" => "Omaheke", + "ON" => "Oshana", + "OS" => "Omusati", + "OT" => "Oshikoto", + "OW" => "Ohangwena" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NC.php new file mode 100644 index 0000000..ca1111b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NC.php @@ -0,0 +1,6 @@ + "New Caledonia", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NE.php new file mode 100644 index 0000000..520e352 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NE.php @@ -0,0 +1,14 @@ + "Niger", + "subdivisions" => [ + "1" => "Agadez", + "2" => "Diffa", + "3" => "Dosso", + "4" => "Maradi", + "5" => "Tahoua", + "6" => "Tillabéri", + "7" => "Zinder", + "8" => "Niamey" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NF.php new file mode 100644 index 0000000..14dbb26 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NF.php @@ -0,0 +1,6 @@ + "Norfolk Island", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NG.php new file mode 100644 index 0000000..3c25c07 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NG.php @@ -0,0 +1,43 @@ + "Nigeria", + "subdivisions" => [ + "AB" => "Abia", + "AD" => "Adamawa", + "AK" => "Akwa Ibom", + "AN" => "Anambra", + "BA" => "Bauchi", + "BE" => "Benue", + "BO" => "Borno", + "BY" => "Bayelsa", + "CR" => "Cross River", + "DE" => "Delta", + "EB" => "Ebonyi", + "ED" => "Edo", + "EK" => "Ekiti", + "EN" => "Enugu", + "FC" => "Abuja Federal Capital Territory", + "GO" => "Gombe", + "IM" => "Imo", + "JI" => "Jigawa", + "KD" => "Kaduna", + "KE" => "Kebbi", + "KN" => "Kano", + "KO" => "Kogi", + "KT" => "Katsina", + "KW" => "Kwara", + "LA" => "Lagos", + "NA" => "Nasarawa", + "NI" => "Niger", + "OG" => "Ogun", + "ON" => "Ondo", + "OS" => "Osun", + "OY" => "Oyo", + "PL" => "Plateau", + "RI" => "Rivers", + "SO" => "Sokoto", + "TA" => "Taraba", + "YO" => "Yobe", + "ZA" => "Zamfara" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NI.php new file mode 100644 index 0000000..b17e901 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NI.php @@ -0,0 +1,23 @@ + "Nicaragua", + "subdivisions" => [ + "AN" => "Costa Caribe Norte", + "AS" => "Costa Caribe Sur", + "BO" => "Boaco", + "CA" => "Carazo", + "CI" => "Chinandega", + "CO" => "Chontales", + "ES" => "Estelí", + "GR" => "Granada", + "JI" => "Jinotega", + "LE" => "León", + "MD" => "Madriz", + "MN" => "Managua", + "MS" => "Masaya", + "MT" => "Matagalpa", + "NS" => "Nueva Segovia", + "RI" => "Rivas", + "SJ" => "Río San Juan" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NL.php new file mode 100644 index 0000000..07efdab --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NL.php @@ -0,0 +1,24 @@ + "Netherlands", + "subdivisions" => [ + "AW" => "Aruba", + "BQ1" => "Bonaire", + "BQ2" => "Saba", + "BQ3" => "Sint Eustatius", + "CW" => "Curaçao", + "DR" => "Drenthe", + "FL" => "Flevoland", + "FR" => "Fryslân", + "GE" => "Gelderland", + "GR" => "Groningen", + "LI" => "Limburg", + "NB" => "Noord-Brabant", + "NH" => "Noord-Holland", + "OV" => "Overijssel", + "SX" => "Sint Maarten", + "UT" => "Utrecht", + "ZE" => "Zeeland", + "ZH" => "Zuid-Holland" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NO.php new file mode 100644 index 0000000..1a5957c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NO.php @@ -0,0 +1,19 @@ + "Norway", + "subdivisions" => [ + "03" => "Oslo", + "11" => "Rogaland", + "15" => "Møre og Romsdal", + "18" => "Nordland", + "21" => "Svalbard (Arctic Region)", + "22" => "Jan Mayen (Arctic Region)", + "30" => "Viken", + "34" => "Innlandet", + "38" => "Vestfold og Telemark", + "42" => "Agder", + "46" => "Vestland", + "50" => "Trööndelage", + "54" => "Romssa ja Finnmárkku" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NP.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NP.php new file mode 100644 index 0000000..7070ab7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NP.php @@ -0,0 +1,32 @@ + "Nepal", + "subdivisions" => [ + "1" => "Central", + "2" => "Mid Western", + "3" => "Western", + "4" => "Eastern", + "5" => "Far Western", + "BA" => "Bagmati", + "BH" => "Bheri", + "DH" => "Dhawalagiri", + "GA" => "Gandaki", + "JA" => "Janakpur", + "KA" => "Karnali", + "KO" => "Kosi", + "LU" => "Lumbini", + "MA" => "Mahakali", + "ME" => "Mechi", + "NA" => "Narayani", + "P1" => "Province 1", + "P2" => "Province 2", + "P3" => "Bāgmatī", + "P4" => "Gandaki", + "P5" => "Province 5", + "P6" => "Karnali", + "P7" => "Sudūr Pashchim", + "RA" => "Rapti", + "SA" => "Sagarmatha", + "SE" => "Seti" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NR.php new file mode 100644 index 0000000..1a0c257 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NR.php @@ -0,0 +1,20 @@ + "Nauru", + "subdivisions" => [ + "01" => "Aiwo", + "02" => "Anabar", + "03" => "Anetan", + "04" => "Anibare", + "05" => "Baitsi", + "06" => "Boe", + "07" => "Buada", + "08" => "Denigomodu", + "09" => "Ewa", + "10" => "Ijuw", + "11" => "Meneng", + "12" => "Nibok", + "13" => "Uaboe", + "14" => "Yaren" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NU.php new file mode 100644 index 0000000..8a53680 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NU.php @@ -0,0 +1,6 @@ + "Niue", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/NZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/NZ.php new file mode 100644 index 0000000..e3b2511 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/NZ.php @@ -0,0 +1,23 @@ + "New Zealand", + "subdivisions" => [ + "AUK" => "Auckland", + "BOP" => "Bay of Plenty", + "CAN" => "Canterbury", + "CIT" => "Chatham Islands Territory", + "GIS" => "Gisborne", + "HKB" => "Hawke's Bay", + "MBH" => "Marlborough", + "MWT" => "Manawatu-Wanganui", + "NSN" => "Nelson", + "NTL" => "Northland", + "OTA" => "Otago", + "STL" => "Southland", + "TAS" => "Tasman", + "TKI" => "Taranaki", + "WGN" => "Wellington", + "WKO" => "Waikato", + "WTC" => "West Coast" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/OM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/OM.php new file mode 100644 index 0000000..afc71da --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/OM.php @@ -0,0 +1,17 @@ + "Oman", + "subdivisions" => [ + "BJ" => "Janūb al Bāţinah", + "BS" => "Shamāl al Bāţinah", + "BU" => "Al Buraymī", + "DA" => "Ad Dākhilīyah", + "MA" => "Masqaţ", + "MU" => "Musandam", + "SJ" => "Janūb ash Sharqīyah", + "SS" => "Shamāl ash Sharqīyah", + "WU" => "Al Wusţá", + "ZA" => "Az̧ Z̧āhirah", + "ZU" => "Z̧ufār" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PA.php new file mode 100644 index 0000000..aa024f7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PA.php @@ -0,0 +1,19 @@ + "Panama", + "subdivisions" => [ + "1" => "Bocas del Toro", + "10" => "Panamá Oeste", + "2" => "Coclé", + "3" => "Colón", + "4" => "Chiriquí", + "5" => "Darién", + "6" => "Herrera", + "7" => "Los Santos", + "8" => "Panamá", + "9" => "Veraguas", + "EM" => "Emberá", + "KY" => "Guna Yala", + "NB" => "Ngöbe-Buglé" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PE.php new file mode 100644 index 0000000..d8683d5 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PE.php @@ -0,0 +1,32 @@ + "Peru", + "subdivisions" => [ + "AMA" => "Amarumayu", + "ANC" => "Ancash", + "APU" => "Apurimaq", + "ARE" => "Arequipa", + "AYA" => "Ayacucho", + "CAJ" => "Cajamarca", + "CAL" => "El Callao", + "CUS" => "Cusco", + "HUC" => "Huánuco", + "HUV" => "Huancavelica", + "ICA" => "Ica", + "JUN" => "Hunin", + "LAL" => "La Libertad", + "LAM" => "Lambayeque", + "LIM" => "Lima", + "LMA" => "Lima hatun llaqta", + "LOR" => "Loreto", + "MDD" => "Madre de Dios", + "MOQ" => "Moquegua", + "PAS" => "Pasco", + "PIU" => "Piura", + "PUN" => "Puno", + "SAM" => "San Martin", + "TAC" => "Tacna", + "TUM" => "Tumbes", + "UCA" => "Ucayali" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PF.php new file mode 100644 index 0000000..5f0980a --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PF.php @@ -0,0 +1,6 @@ + "French Polynesia", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PG.php new file mode 100644 index 0000000..635cd3a --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PG.php @@ -0,0 +1,28 @@ + "Papua New Guinea", + "subdivisions" => [ + "CPK" => "Chimbu", + "CPM" => "Central", + "EBR" => "East New Britain", + "EHG" => "Eastern Highlands", + "EPW" => "Enga", + "ESW" => "East Sepik", + "GPK" => "Gulf", + "HLA" => "Hela", + "JWK" => "Jiwaka", + "MBA" => "Milne Bay", + "MPL" => "Morobe", + "MPM" => "Madang", + "MRL" => "Manus", + "NCD" => "National Capital District (Port Moresby)", + "NIK" => "New Ireland", + "NPP" => "Northern", + "NSB" => "Bougainville", + "SAN" => "West Sepik", + "SHM" => "Southern Highlands", + "WBK" => "West New Britain", + "WHM" => "Western Highlands", + "WPD" => "Western" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PH.php new file mode 100644 index 0000000..e38cbde --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PH.php @@ -0,0 +1,104 @@ + "Philippines", + "subdivisions" => [ + "00" => "National Capital Region", + "01" => "Ilocos (Region I)", + "02" => "Cagayan Valley (Region II)", + "03" => "Central Luzon (Region III)", + "05" => "Bicol (Region V)", + "06" => "Western Visayas (Region VI)", + "07" => "Central Visayas (Region VII)", + "08" => "Eastern Visayas (Region VIII)", + "09" => "Zamboanga Peninsula (Region IX)", + "10" => "Northern Mindanao (Region X)", + "11" => "Davao (Region XI)", + "12" => "Soccsksargen (Region XII)", + "13" => "Caraga (Region XIII)", + "14" => "Autonomous Region in Muslim Mindanao (ARMM)", + "15" => "Cordillera Administrative Region (CAR)", + "40" => "Calabarzon (Region IV-A)", + "41" => "Mimaropa (Region IV-B)", + "ABR" => "Abra", + "AGN" => "Agusan del Norte", + "AGS" => "Agusan del Sur", + "AKL" => "Aklan", + "ALB" => "Albay", + "ANT" => "Antique", + "APA" => "Apayao", + "AUR" => "Aurora", + "BAN" => "Bataan", + "BAS" => "Basilan", + "BEN" => "Benguet", + "BIL" => "Biliran", + "BOH" => "Bohol", + "BTG" => "Batangas", + "BTN" => "Batanes", + "BUK" => "Bukidnon", + "BUL" => "Bulacan", + "CAG" => "Cagayan", + "CAM" => "Camiguin", + "CAN" => "Camarines Norte", + "CAP" => "Capiz", + "CAS" => "Camarines Sur", + "CAT" => "Catanduanes", + "CAV" => "Cavite", + "CEB" => "Cebu", + "COM" => "Davao de Oro", + "DAO" => "Davao Oriental", + "DAS" => "Davao del Sur", + "DAV" => "Davao del Norte", + "DIN" => "Dinagat Islands", + "DVO" => "Davao Occidental", + "EAS" => "Eastern Samar", + "GUI" => "Guimaras", + "IFU" => "Ifugao", + "ILI" => "Iloilo", + "ILN" => "Ilocos Norte", + "ILS" => "Ilocos Sur", + "ISA" => "Isabela", + "KAL" => "Kalinga", + "LAG" => "Laguna", + "LAN" => "Lanao del Norte", + "LAS" => "Lanao del Sur", + "LEY" => "Leyte", + "LUN" => "La Union", + "MAD" => "Marinduque", + "MAG" => "Maguindanao", + "MAS" => "Masbate", + "MDC" => "Mindoro Occidental", + "MDR" => "Mindoro Oriental", + "MOU" => "Mountain Province", + "MSC" => "Misamis Occidental", + "MSR" => "Misamis Oriental", + "NCO" => "Cotabato", + "NEC" => "Negros Occidental", + "NER" => "Negros Oriental", + "NSA" => "Northern Samar", + "NUE" => "Nueva Ecija", + "NUV" => "Nueva Vizcaya", + "PAM" => "Pampanga", + "PAN" => "Pangasinan", + "PLW" => "Palawan", + "QUE" => "Quezon", + "QUI" => "Quirino", + "RIZ" => "Rizal", + "ROM" => "Romblon", + "SAR" => "Sarangani", + "SCO" => "South Cotabato", + "SIG" => "Siquijor", + "SLE" => "Southern Leyte", + "SLU" => "Sulu", + "SOR" => "Sorsogon", + "SUK" => "Sultan Kudarat", + "SUN" => "Surigao del Norte", + "SUR" => "Surigao del Sur", + "TAR" => "Tarlac", + "TAW" => "Tawi-Tawi", + "WSA" => "Samar", + "ZAN" => "Zamboanga del Norte", + "ZAS" => "Zamboanga del Sur", + "ZMB" => "Zambales", + "ZSI" => "Zamboanga Sibugay" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PK.php new file mode 100644 index 0000000..a6883c6 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PK.php @@ -0,0 +1,13 @@ + "Pakistan", + "subdivisions" => [ + "BA" => "Balochistan", + "GB" => "Gilgit-Baltistan", + "IS" => "Islamabad", + "JK" => "Azad Jammu and Kashmir", + "KP" => "Khyber Pakhtunkhwa", + "PB" => "Punjab", + "SD" => "Sindh" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PL.php new file mode 100644 index 0000000..b7a29be --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PL.php @@ -0,0 +1,22 @@ + "Poland", + "subdivisions" => [ + "02" => "Dolnośląskie", + "04" => "Kujawsko-pomorskie", + "06" => "Lubelskie", + "08" => "Lubuskie", + "10" => "Łódzkie", + "12" => "Małopolskie", + "14" => "Mazowieckie", + "16" => "Opolskie", + "18" => "Podkarpackie", + "20" => "Podlaskie", + "22" => "Pomorskie", + "24" => "Śląskie", + "26" => "Świętokrzyskie", + "28" => "Warmińsko-mazurskie", + "30" => "Wielkopolskie", + "32" => "Zachodniopomorskie" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PM.php new file mode 100644 index 0000000..3fe454f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PM.php @@ -0,0 +1,6 @@ + "Saint Pierre and Miquelon", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PN.php new file mode 100644 index 0000000..b02ad2b --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PN.php @@ -0,0 +1,6 @@ + "Pitcairn", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PR.php new file mode 100644 index 0000000..820e512 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PR.php @@ -0,0 +1,6 @@ + "Puerto Rico", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PS.php new file mode 100644 index 0000000..a42378c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PS.php @@ -0,0 +1,22 @@ + "Palestine, State of", + "subdivisions" => [ + "BTH" => "Bethlehem", + "DEB" => "Deir El Balah", + "GZA" => "Gaza", + "HBN" => "Hebron", + "JEM" => "Jerusalem", + "JEN" => "Jenin", + "JRH" => "Jericho and Al Aghwar", + "KYS" => "Khan Yunis", + "NBS" => "Nablus", + "NGZ" => "North Gaza", + "QQA" => "Qalqilya", + "RBH" => "Ramallah", + "RFH" => "Rafah", + "SLT" => "Salfit", + "TBS" => "Tubas", + "TKM" => "Tulkarm" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PT.php new file mode 100644 index 0000000..1f0f798 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PT.php @@ -0,0 +1,26 @@ + "Portugal", + "subdivisions" => [ + "01" => "Aveiro", + "02" => "Beja", + "03" => "Braga", + "04" => "Bragança", + "05" => "Castelo Branco", + "06" => "Coimbra", + "07" => "Évora", + "08" => "Faro", + "09" => "Guarda", + "10" => "Leiria", + "11" => "Lisboa", + "12" => "Portalegre", + "13" => "Porto", + "14" => "Santarém", + "15" => "Setúbal", + "16" => "Viana do Castelo", + "17" => "Vila Real", + "18" => "Viseu", + "20" => "Região Autónoma dos Açores", + "30" => "Região Autónoma da Madeira" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PW.php new file mode 100644 index 0000000..864834f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PW.php @@ -0,0 +1,22 @@ + "Palau", + "subdivisions" => [ + "002" => "Aimeliik", + "004" => "Airai", + "010" => "Angaur", + "050" => "Hatohobei", + "100" => "Kayangel", + "150" => "Koror", + "212" => "Melekeok", + "214" => "Ngaraard", + "218" => "Ngarchelong", + "222" => "Ngardmau", + "224" => "Ngatpang", + "226" => "Ngchesar", + "227" => "Ngeremlengui", + "228" => "Ngiwal", + "350" => "Peleliu", + "370" => "Sonsorol" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/PY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/PY.php new file mode 100644 index 0000000..a64c860 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/PY.php @@ -0,0 +1,24 @@ + "Paraguay", + "subdivisions" => [ + "1" => "Concepción", + "10" => "Alto Paraná", + "11" => "Central", + "12" => "Ñeembucú", + "13" => "Amambay", + "14" => "Canindeyú", + "15" => "Presidente Hayes", + "16" => "Alto Paraguay", + "19" => "Boquerón", + "2" => "San Pedro", + "3" => "Cordillera", + "4" => "Guairá", + "5" => "Caaguazú", + "6" => "Caazapá", + "7" => "Itapúa", + "8" => "Misiones", + "9" => "Paraguarí", + "ASU" => "Asunción" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/QA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/QA.php new file mode 100644 index 0000000..7592474 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/QA.php @@ -0,0 +1,14 @@ + "Qatar", + "subdivisions" => [ + "DA" => "Ad Dawḩah", + "KH" => "Al Khawr wa adh Dhakhīrah", + "MS" => "Ash Shamāl", + "RA" => "Ar Rayyān", + "SH" => "Ash Shīḩānīyah", + "US" => "Umm Şalāl", + "WA" => "Al Wakrah", + "ZA" => "Az̧ Z̧a‘āyin" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/RE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/RE.php new file mode 100644 index 0000000..4d650ec --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/RE.php @@ -0,0 +1,6 @@ + "Réunion", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/RO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/RO.php new file mode 100644 index 0000000..227298a --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/RO.php @@ -0,0 +1,48 @@ + "Romania", + "subdivisions" => [ + "AB" => "Alba", + "AG" => "Argeș", + "AR" => "Arad", + "B" => "București", + "BC" => "Bacău", + "BH" => "Bihor", + "BN" => "Bistrița-Năsăud", + "BR" => "Brăila", + "BT" => "Botoșani", + "BV" => "Brașov", + "BZ" => "Buzău", + "CJ" => "Cluj", + "CL" => "Călărași", + "CS" => "Caraș-Severin", + "CT" => "Constanța", + "CV" => "Covasna", + "DB" => "Dâmbovița", + "DJ" => "Dolj", + "GJ" => "Gorj", + "GL" => "Galați", + "GR" => "Giurgiu", + "HD" => "Hunedoara", + "HR" => "Harghita", + "IF" => "Ilfov", + "IL" => "Ialomița", + "IS" => "Iași", + "MH" => "Mehedinți", + "MM" => "Maramureș", + "MS" => "Mureș", + "NT" => "Neamț", + "OT" => "Olt", + "PH" => "Prahova", + "SB" => "Sibiu", + "SJ" => "Sălaj", + "SM" => "Satu Mare", + "SV" => "Suceava", + "TL" => "Tulcea", + "TM" => "Timiș", + "TR" => "Teleorman", + "VL" => "Vâlcea", + "VN" => "Vrancea", + "VS" => "Vaslui" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/RS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/RS.php new file mode 100644 index 0000000..d8f6c3f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/RS.php @@ -0,0 +1,38 @@ + "Serbia", + "subdivisions" => [ + "00" => "Beograd", + "01" => "Severnobački okrug", + "02" => "Srednjebanatski okrug", + "03" => "Severnobanatski okrug", + "04" => "Južnobanatski okrug", + "05" => "Zapadnobački okrug", + "06" => "Južnobački okrug", + "07" => "Sremski okrug", + "08" => "Mačvanski okrug", + "09" => "Kolubarski okrug", + "10" => "Podunavski okrug", + "11" => "Braničevski okrug", + "12" => "Šumadijski okrug", + "13" => "Pomoravski okrug", + "14" => "Borski okrug", + "15" => "Zaječarski okrug", + "16" => "Zlatiborski okrug", + "17" => "Moravički okrug", + "18" => "Raški okrug", + "19" => "Rasinski okrug", + "20" => "Nišavski okrug", + "21" => "Toplički okrug", + "22" => "Pirotski okrug", + "23" => "Jablanički okrug", + "24" => "Pčinjski okrug", + "25" => "Kosovski okrug", + "26" => "Pećki okrug", + "27" => "Prizrenski okrug", + "28" => "Kosovsko-Mitrovački okrug", + "29" => "Kosovsko-Pomoravski okrug", + "KM" => "Kosovo-Metohija", + "VO" => "Vojvodina" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/RU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/RU.php new file mode 100644 index 0000000..a4e195c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/RU.php @@ -0,0 +1,89 @@ + "Russian Federation", + "subdivisions" => [ + "AD" => "Adygeja, Respublika", + "AL" => "Altaj, Respublika", + "ALT" => "Altajskij kraj", + "AMU" => "Amurskaja oblast'", + "ARK" => "Arhangel'skaja oblast'", + "AST" => "Astrahanskaja oblast'", + "BA" => "Bashkortostan, Respublika", + "BEL" => "Belgorodskaja oblast'", + "BRY" => "Brjanskaja oblast'", + "BU" => "Burjatija, Respublika", + "CE" => "Chechenskaya Respublika", + "CHE" => "Chelyabinskaya oblast'", + "CHU" => "Chukotskiy avtonomnyy okrug", + "CU" => "Chuvashskaya Respublika", + "DA" => "Dagestan, Respublika", + "IN" => "Ingushetiya, Respublika", + "IRK" => "Irkutskaja oblast'", + "IVA" => "Ivanovskaja oblast'", + "KAM" => "Kamchatskiy kray", + "KB" => "Kabardino-Balkarskaja Respublika", + "KC" => "Karachayevo-Cherkesskaya Respublika", + "KDA" => "Krasnodarskij kraj", + "KEM" => "Kemerovskaja oblast'", + "KGD" => "Kaliningradskaja oblast'", + "KGN" => "Kurganskaja oblast'", + "KHA" => "Habarovskij kraj", + "KHM" => "Hanty-Mansijskij avtonomnyj okrug", + "KIR" => "Kirovskaja oblast'", + "KK" => "Hakasija, Respublika", + "KL" => "Kalmykija, Respublika", + "KLU" => "Kaluzhskaya oblast'", + "KO" => "Komi, Respublika", + "KOS" => "Kostromskaja oblast'", + "KR" => "Karelija, Respublika", + "KRS" => "Kurskaja oblast'", + "KYA" => "Krasnojarskij kraj", + "LEN" => "Leningradskaja oblast'", + "LIP" => "Lipeckaja oblast'", + "MAG" => "Magadanskaja oblast'", + "ME" => "Marij Èl, Respublika", + "MO" => "Mordovija, Respublika", + "MOS" => "Moskovskaja oblast'", + "MOW" => "Moskva", + "MUR" => "Murmanskaja oblast'", + "NEN" => "Neneckij avtonomnyj okrug", + "NGR" => "Novgorodskaja oblast'", + "NIZ" => "Nizhegorodskaya oblast'", + "NVS" => "Novosibirskaja oblast'", + "OMS" => "Omskaja oblast'", + "ORE" => "Orenburgskaja oblast'", + "ORL" => "Orlovskaja oblast'", + "PER" => "Permskij kraj", + "PNZ" => "Penzenskaja oblast'", + "PRI" => "Primorskij kraj", + "PSK" => "Pskovskaja oblast'", + "ROS" => "Rostovskaja oblast'", + "RYA" => "Rjazanskaja oblast'", + "SA" => "Saha, Respublika", + "SAK" => "Sahalinskaja oblast'", + "SAM" => "Samarskaja oblast'", + "SAR" => "Saratovskaja oblast'", + "SE" => "Severnaja Osetija, Respublika", + "SMO" => "Smolenskaja oblast'", + "SPE" => "Sankt-Peterburg", + "STA" => "Stavropol'skij kraj", + "SVE" => "Sverdlovskaja oblast'", + "TA" => "Tatarstan, Respublika", + "TAM" => "Tambovskaja oblast'", + "TOM" => "Tomskaja oblast'", + "TUL" => "Tul'skaja oblast'", + "TVE" => "Tverskaja oblast'", + "TY" => "Tyva, Respublika", + "TYU" => "Tjumenskaja oblast'", + "UD" => "Udmurtskaja Respublika", + "ULY" => "Ul'janovskaja oblast'", + "VGG" => "Volgogradskaja oblast'", + "VLA" => "Vladimirskaja oblast'", + "VLG" => "Vologodskaja oblast'", + "VOR" => "Voronezhskaya oblast'", + "YAN" => "Jamalo-Neneckij avtonomnyj okrug", + "YAR" => "Jaroslavskaja oblast'", + "YEV" => "Evrejskaja avtonomnaja oblast'", + "ZAB" => "Zabajkal'skij kraj" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/RW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/RW.php new file mode 100644 index 0000000..bc3720c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/RW.php @@ -0,0 +1,11 @@ + "Rwanda", + "subdivisions" => [ + "01" => "City of Kigali", + "02" => "Eastern", + "03" => "Northern", + "04" => "Western", + "05" => "Southern" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SA.php new file mode 100644 index 0000000..50a3165 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SA.php @@ -0,0 +1,19 @@ + "Saudi Arabia", + "subdivisions" => [ + "01" => "Ar Riyāḑ", + "02" => "Makkah al Mukarramah", + "03" => "Al Madīnah al Munawwarah", + "04" => "Ash Sharqīyah", + "05" => "Al Qaşīm", + "06" => "Ḩā'il", + "07" => "Tabūk", + "08" => "Al Ḩudūd ash Shamālīyah", + "09" => "Jāzān", + "10" => "Najrān", + "11" => "Al Bāḩah", + "12" => "Al Jawf", + "14" => "'Asīr" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SB.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SB.php new file mode 100644 index 0000000..0b3b6e7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SB.php @@ -0,0 +1,16 @@ + "Solomon Islands", + "subdivisions" => [ + "CE" => "Central", + "CH" => "Choiseul", + "CT" => "Capital Territory (Honiara)", + "GU" => "Guadalcanal", + "IS" => "Isabel", + "MK" => "Makira-Ulawa", + "ML" => "Malaita", + "RB" => "Rennell and Bellona", + "TE" => "Temotu", + "WE" => "Western" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SC.php new file mode 100644 index 0000000..5c22e8f --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SC.php @@ -0,0 +1,33 @@ + "Seychelles", + "subdivisions" => [ + "01" => "Anse aux Pins", + "02" => "Anse Boileau", + "03" => "Anse Etoile", + "04" => "Au Cap", + "05" => "Anse Royale", + "06" => "Baie Lazare", + "07" => "Baie Sainte Anne", + "08" => "Beau Vallon", + "09" => "Bel Air", + "10" => "Bel Ombre", + "11" => "Cascade", + "12" => "Glacis", + "13" => "Grand Anse Mahe", + "14" => "Grand Anse Praslin", + "15" => "La Digue", + "16" => "English River", + "17" => "Mont Buxton", + "18" => "Mont Fleuri", + "19" => "Plaisance", + "20" => "Pointe Larue", + "21" => "Port Glaud", + "22" => "Saint Louis", + "23" => "Takamaka", + "24" => "Les Mamelles", + "25" => "Roche Caiman", + "26" => "Ile Perseverance I", + "27" => "Ile Perseverance II" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SD.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SD.php new file mode 100644 index 0000000..ad17338 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SD.php @@ -0,0 +1,24 @@ + "Sudan", + "subdivisions" => [ + "DC" => "Central Darfur", + "DE" => "East Darfur", + "DN" => "North Darfur", + "DS" => "South Darfur", + "DW" => "West Darfur", + "GD" => "Gedaref", + "GK" => "West Kordofan", + "GZ" => "Gezira", + "KA" => "Kassala", + "KH" => "Khartoum", + "KN" => "North Kordofan", + "KS" => "South Kordofan", + "NB" => "Blue Nile", + "NO" => "Northern", + "NR" => "River Nile", + "NW" => "White Nile", + "RS" => "Red Sea", + "SI" => "Sennar" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SE.php new file mode 100644 index 0000000..d4564e3 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SE.php @@ -0,0 +1,27 @@ + "Sweden", + "subdivisions" => [ + "AB" => "Stockholms län [SE-01]", + "AC" => "Västerbottens län [SE-24]", + "BD" => "Norrbottens län [SE-25]", + "C" => "Uppsala län [SE-03]", + "D" => "Södermanlands län [SE-04]", + "E" => "Östergötlands län [SE-05]", + "F" => "Jönköpings län [SE-06]", + "G" => "Kronobergs län [SE-07]", + "H" => "Kalmar län [SE-08]", + "I" => "Gotlands län [SE-09]", + "K" => "Blekinge län [SE-10]", + "M" => "Skåne län [SE-12]", + "N" => "Hallands län [SE-13]", + "O" => "Västra Götalands län [SE-14]", + "S" => "Värmlands län [SE-17]", + "T" => "Örebro län [SE-18]", + "U" => "Västmanlands län [SE-19]", + "W" => "Dalarnas län [SE-20]", + "X" => "Gävleborgs län [SE-21]", + "Y" => "Västernorrlands län [SE-22]", + "Z" => "Jämtlands län [SE-23]" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SG.php new file mode 100644 index 0000000..2cdc5f0 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SG.php @@ -0,0 +1,11 @@ + "Singapore", + "subdivisions" => [ + "01" => "Central Singapore", + "02" => "North East", + "03" => "North West", + "04" => "South East", + "05" => "South West" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SH.php new file mode 100644 index 0000000..e62fbc9 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SH.php @@ -0,0 +1,9 @@ + "Saint Helena, Ascension and Tristan da Cunha", + "subdivisions" => [ + "AC" => "Ascension", + "HL" => "Saint Helena", + "TA" => "Tristan da Cunha" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SI.php new file mode 100644 index 0000000..3dddbe5 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SI.php @@ -0,0 +1,218 @@ + "Slovenia", + "subdivisions" => [ + "001" => "Ajdovščina", + "002" => "Beltinci", + "003" => "Bled", + "004" => "Bohinj", + "005" => "Borovnica", + "006" => "Bovec", + "007" => "Brda", + "008" => "Brezovica", + "009" => "Brežice", + "010" => "Tišina", + "011" => "Celje", + "012" => "Cerklje na Gorenjskem", + "013" => "Cerknica", + "014" => "Cerkno", + "015" => "Črenšovci", + "016" => "Črna na Koroškem", + "017" => "Črnomelj", + "018" => "Destrnik", + "019" => "Divača", + "020" => "Dobrepolje", + "021" => "Dobrova-Polhov Gradec", + "022" => "Dol pri Ljubljani", + "023" => "Domžale", + "024" => "Dornava", + "025" => "Dravograd", + "026" => "Duplek", + "027" => "Gorenja vas-Poljane", + "028" => "Gorišnica", + "029" => "Gornja Radgona", + "030" => "Gornji Grad", + "031" => "Gornji Petrovci", + "032" => "Grosuplje", + "033" => "Šalovci", + "034" => "Hrastnik", + "035" => "Hrpelje-Kozina", + "036" => "Idrija", + "037" => "Ig", + "038" => "Ilirska Bistrica", + "039" => "Ivančna Gorica", + "040" => "Izola", + "041" => "Jesenice", + "042" => "Juršinci", + "043" => "Kamnik", + "044" => "Kanal", + "045" => "Kidričevo", + "046" => "Kobarid", + "047" => "Kobilje", + "048" => "Kočevje", + "049" => "Komen", + "050" => "Koper", + "051" => "Kozje", + "052" => "Kranj", + "053" => "Kranjska Gora", + "054" => "Krško", + "055" => "Kungota", + "056" => "Kuzma", + "057" => "Laško", + "058" => "Lenart", + "059" => "Lendava", + "060" => "Litija", + "061" => "Ljubljana", + "062" => "Ljubno", + "063" => "Ljutomer", + "064" => "Logatec", + "065" => "Loška dolina", + "066" => "Loški Potok", + "067" => "Luče", + "068" => "Lukovica", + "069" => "Majšperk", + "070" => "Maribor", + "071" => "Medvode", + "072" => "Mengeš", + "073" => "Metlika", + "074" => "Mežica", + "075" => "Miren-Kostanjevica", + "076" => "Mislinja", + "077" => "Moravče", + "078" => "Moravske Toplice", + "079" => "Mozirje", + "080" => "Murska Sobota", + "081" => "Muta", + "082" => "Naklo", + "083" => "Nazarje", + "084" => "Nova Gorica", + "085" => "Novo Mesto", + "086" => "Odranci", + "087" => "Ormož", + "088" => "Osilnica", + "089" => "Pesnica", + "090" => "Piran", + "091" => "Pivka", + "092" => "Podčetrtek", + "093" => "Podvelka", + "094" => "Postojna", + "095" => "Preddvor", + "096" => "Ptuj", + "097" => "Puconci", + "098" => "Rače-Fram", + "099" => "Radeče", + "100" => "Radenci", + "101" => "Radlje ob Dravi", + "102" => "Radovljica", + "103" => "Ravne na Koroškem", + "104" => "Ribnica", + "105" => "Rogašovci", + "106" => "Rogaška Slatina", + "107" => "Rogatec", + "108" => "Ruše", + "109" => "Semič", + "110" => "Sevnica", + "111" => "Sežana", + "112" => "Slovenj Gradec", + "113" => "Slovenska Bistrica", + "114" => "Slovenske Konjice", + "115" => "Starše", + "116" => "Sveti Jurij ob Ščavnici", + "117" => "Šenčur", + "118" => "Šentilj", + "119" => "Šentjernej", + "120" => "Šentjur", + "121" => "Škocjan", + "122" => "Škofja Loka", + "123" => "Škofljica", + "124" => "Šmarje pri Jelšah", + "125" => "Šmartno ob Paki", + "126" => "Šoštanj", + "127" => "Štore", + "128" => "Tolmin", + "129" => "Trbovlje", + "130" => "Trebnje", + "131" => "Tržič", + "132" => "Turnišče", + "133" => "Velenje", + "134" => "Velike Lašče", + "135" => "Videm", + "136" => "Vipava", + "137" => "Vitanje", + "138" => "Vodice", + "139" => "Vojnik", + "140" => "Vrhnika", + "141" => "Vuzenica", + "142" => "Zagorje ob Savi", + "143" => "Zavrč", + "144" => "Zreče", + "146" => "Železniki", + "147" => "Žiri", + "148" => "Benedikt", + "149" => "Bistrica ob Sotli", + "150" => "Bloke", + "151" => "Braslovče", + "152" => "Cankova", + "153" => "Cerkvenjak", + "154" => "Dobje", + "155" => "Dobrna", + "156" => "Dobrovnik", + "157" => "Dolenjske Toplice", + "158" => "Grad", + "159" => "Hajdina", + "160" => "Hoče-Slivnica", + "161" => "Hodoš", + "162" => "Horjul", + "163" => "Jezersko", + "164" => "Komenda", + "165" => "Kostel", + "166" => "Križevci", + "167" => "Lovrenc na Pohorju", + "168" => "Markovci", + "169" => "Miklavž na Dravskem polju", + "170" => "Mirna Peč", + "171" => "Oplotnica", + "172" => "Podlehnik", + "173" => "Polzela", + "174" => "Prebold", + "175" => "Prevalje", + "176" => "Razkrižje", + "177" => "Ribnica na Pohorju", + "178" => "Selnica ob Dravi", + "179" => "Sodražica", + "180" => "Solčava", + "181" => "Sveta Ana", + "182" => "Sveti Andraž v Slovenskih goricah", + "183" => "Šempeter-Vrtojba", + "184" => "Tabor", + "185" => "Trnovska Vas", + "186" => "Trzin", + "187" => "Velika Polana", + "188" => "Veržej", + "189" => "Vransko", + "190" => "Žalec", + "191" => "Žetale", + "192" => "Žirovnica", + "193" => "Žužemberk", + "194" => "Šmartno pri Litiji", + "195" => "Apače", + "196" => "Cirkulane", + "197" => "Kosanjevica na Krki", + "198" => "Makole", + "199" => "Mokronog-Trebelno", + "200" => "Poljčane", + "201" => "Renče-Vogrsko", + "202" => "Središče ob Dravi", + "203" => "Straža", + "204" => "Sveta Trojica v Slovenskih goricah", + "205" => "Sveti Tomaž", + "206" => "Šmarješke Toplice", + "207" => "Gorje", + "208" => "Log-Dragomer", + "209" => "Rečica ob Savinji", + "210" => "Sveti Jurij v Slovenskih goricah", + "211" => "Šentrupert", + "212" => "Mirna", + "213" => "Ankaran" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SJ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SJ.php new file mode 100644 index 0000000..d6ec3a2 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SJ.php @@ -0,0 +1,6 @@ + "Svalbard and Jan Mayen", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SK.php new file mode 100644 index 0000000..a465575 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SK.php @@ -0,0 +1,14 @@ + "Slovakia", + "subdivisions" => [ + "BC" => "Banskobystrický kraj", + "BL" => "Bratislavský kraj", + "KI" => "Košický kraj", + "NI" => "Nitriansky kraj", + "PV" => "Prešovský kraj", + "TA" => "Trnavský kraj", + "TC" => "Trenčiansky kraj", + "ZI" => "Žilinský kraj" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SL.php new file mode 100644 index 0000000..ece10b2 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SL.php @@ -0,0 +1,11 @@ + "Sierra Leone", + "subdivisions" => [ + "E" => "Eastern", + "N" => "Northern", + "NW" => "North Western", + "S" => "Southern", + "W" => "Western Area (Freetown)" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SM.php new file mode 100644 index 0000000..d49dd04 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SM.php @@ -0,0 +1,15 @@ + "San Marino", + "subdivisions" => [ + "01" => "Acquaviva", + "02" => "Chiesanuova", + "03" => "Domagnano", + "04" => "Faetano", + "05" => "Fiorentino", + "06" => "Borgo Maggiore", + "07" => "Città di San Marino", + "08" => "Montegiardino", + "09" => "Serravalle" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SN.php new file mode 100644 index 0000000..60119ce --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SN.php @@ -0,0 +1,20 @@ + "Senegal", + "subdivisions" => [ + "DB" => "Diourbel", + "DK" => "Dakar", + "FK" => "Fatick", + "KA" => "Kaffrine", + "KD" => "Kolda", + "KE" => "Kédougou", + "KL" => "Kaolack", + "LG" => "Louga", + "MT" => "Matam", + "SE" => "Sédhiou", + "SL" => "Saint-Louis", + "TC" => "Tambacounda", + "TH" => "Thiès", + "ZG" => "Ziguinchor" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SO.php new file mode 100644 index 0000000..3ab88a4 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SO.php @@ -0,0 +1,24 @@ + "Somalia", + "subdivisions" => [ + "AW" => "Awdal", + "BK" => "Bakool", + "BN" => "Banaadir", + "BR" => "Bari", + "BY" => "Bay", + "GA" => "Galguduud", + "GE" => "Gedo", + "HI" => "Hiiraan", + "JD" => "Jubbada Dhexe", + "JH" => "Jubbada Hoose", + "MU" => "Mudug", + "NU" => "Nugaal", + "SA" => "Sanaag", + "SD" => "Shabeellaha Dhexe", + "SH" => "Shabeellaha Hoose", + "SO" => "Sool", + "TO" => "Togdheer", + "WO" => "Woqooyi Galbeed" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SR.php new file mode 100644 index 0000000..e835eef --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SR.php @@ -0,0 +1,16 @@ + "Suriname", + "subdivisions" => [ + "BR" => "Brokopondo", + "CM" => "Commewijne", + "CR" => "Coronie", + "MA" => "Marowijne", + "NI" => "Nickerie", + "PM" => "Paramaribo", + "PR" => "Para", + "SA" => "Saramacca", + "SI" => "Sipaliwini", + "WA" => "Wanica" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SS.php new file mode 100644 index 0000000..28b6d17 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SS.php @@ -0,0 +1,16 @@ + "South Sudan", + "subdivisions" => [ + "BN" => "Northern Bahr el Ghazal", + "BW" => "Western Bahr el Ghazal", + "EC" => "Central Equatoria", + "EE" => "Eastern Equatoria", + "EW" => "Western Equatoria", + "JG" => "Jonglei", + "LK" => "Lakes", + "NU" => "Upper Nile", + "UY" => "Unity", + "WR" => "Warrap" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ST.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ST.php new file mode 100644 index 0000000..2dcb997 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ST.php @@ -0,0 +1,13 @@ + "Sao Tome and Principe", + "subdivisions" => [ + "01" => "Água Grande", + "02" => "Cantagalo", + "03" => "Caué", + "04" => "Lembá", + "05" => "Lobata", + "06" => "Mé-Zóchi", + "P" => "Príncipe" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SV.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SV.php new file mode 100644 index 0000000..e28919d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SV.php @@ -0,0 +1,20 @@ + "El Salvador", + "subdivisions" => [ + "AH" => "Ahuachapán", + "CA" => "Cabañas", + "CH" => "Chalatenango", + "CU" => "Cuscatlán", + "LI" => "La Libertad", + "MO" => "Morazán", + "PA" => "La Paz", + "SA" => "Santa Ana", + "SM" => "San Miguel", + "SO" => "Sonsonate", + "SS" => "San Salvador", + "SV" => "San Vicente", + "UN" => "La Unión", + "US" => "Usulután" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SX.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SX.php new file mode 100644 index 0000000..ec9de88 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SX.php @@ -0,0 +1,6 @@ + "Sint Maarten (Dutch part)", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SY.php new file mode 100644 index 0000000..185cf27 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SY.php @@ -0,0 +1,20 @@ + "Syrian Arab Republic", + "subdivisions" => [ + "DI" => "Dimashq", + "DR" => "Dar'ā", + "DY" => "Dayr az Zawr", + "HA" => "Al Ḩasakah", + "HI" => "Ḩimş", + "HL" => "Ḩalab", + "HM" => "Ḩamāh", + "ID" => "Idlib", + "LA" => "Al Lādhiqīyah", + "QU" => "Al Qunayţirah", + "RA" => "Ar Raqqah", + "RD" => "Rīf Dimashq", + "SU" => "As Suwaydā'", + "TA" => "Ţarţūs" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/SZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/SZ.php new file mode 100644 index 0000000..a930525 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/SZ.php @@ -0,0 +1,10 @@ + "Eswatini", + "subdivisions" => [ + "HH" => "Hhohho", + "LU" => "Lubombo", + "MA" => "Manzini", + "SH" => "Shiselweni" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TC.php new file mode 100644 index 0000000..64fdafa --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TC.php @@ -0,0 +1,6 @@ + "Turks and Caicos Islands", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TD.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TD.php new file mode 100644 index 0000000..ba324e2 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TD.php @@ -0,0 +1,29 @@ + "Chad", + "subdivisions" => [ + "BA" => "Al Baţḩā’", + "BG" => "Bahr el Ghazal", + "BO" => "Borkou", + "CB" => "Chari-Baguirmi", + "EE" => "Ennedi-Est", + "EO" => "Ennedi-Ouest", + "GR" => "Guéra", + "HL" => "Hadjer Lamis", + "KA" => "Kanem", + "LC" => "Al Buḩayrah", + "LO" => "Logone-Occidental", + "LR" => "Logone-Oriental", + "MA" => "Mandoul", + "MC" => "Moyen-Chari", + "ME" => "Mayo-Kebbi-Est", + "MO" => "Mayo-Kebbi-Ouest", + "ND" => "Madīnat Injamīnā", + "OD" => "Ouaddaï", + "SA" => "Salamat", + "SI" => "Sila", + "TA" => "Tandjilé", + "TI" => "Tibastī", + "WF" => "Wadi Fira" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TF.php new file mode 100644 index 0000000..db7cd16 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TF.php @@ -0,0 +1,6 @@ + "French Southern Territories", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TG.php new file mode 100644 index 0000000..58d97fe --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TG.php @@ -0,0 +1,11 @@ + "Togo", + "subdivisions" => [ + "C" => "Centrale", + "K" => "Kara", + "M" => "Maritime (Région)", + "P" => "Plateaux", + "S" => "Savanes" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TH.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TH.php new file mode 100644 index 0000000..ef24873 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TH.php @@ -0,0 +1,84 @@ + "Thailand", + "subdivisions" => [ + "10" => "Krung Thep Maha Nakhon", + "11" => "Samut Prakan", + "12" => "Nonthaburi", + "13" => "Pathum Thani", + "14" => "Phra Nakhon Si Ayutthaya", + "15" => "Ang Thong", + "16" => "Lop Buri", + "17" => "Sing Buri", + "18" => "Chai Nat", + "19" => "Saraburi", + "20" => "Chon Buri", + "21" => "Rayong", + "22" => "Chanthaburi", + "23" => "Trat", + "24" => "Chachoengsao", + "25" => "Prachin Buri", + "26" => "Nakhon Nayok", + "27" => "Sa Kaeo", + "30" => "Nakhon Ratchasima", + "31" => "Buri Ram", + "32" => "Surin", + "33" => "Si Sa Ket", + "34" => "Ubon Ratchathani", + "35" => "Yasothon", + "36" => "Chaiyaphum", + "37" => "Amnat Charoen", + "38" => "Bueng Kan", + "39" => "Nong Bua Lam Phu", + "40" => "Khon Kaen", + "41" => "Udon Thani", + "42" => "Loei", + "43" => "Nong Khai", + "44" => "Maha Sarakham", + "45" => "Roi Et", + "46" => "Kalasin", + "47" => "Sakon Nakhon", + "48" => "Nakhon Phanom", + "49" => "Mukdahan", + "50" => "Chiang Mai", + "51" => "Lamphun", + "52" => "Lampang", + "53" => "Uttaradit", + "54" => "Phrae", + "55" => "Nan", + "56" => "Phayao", + "57" => "Chiang Rai", + "58" => "Mae Hong Son", + "60" => "Nakhon Sawan", + "61" => "Uthai Thani", + "62" => "Kamphaeng Phet", + "63" => "Tak", + "64" => "Sukhothai", + "65" => "Phitsanulok", + "66" => "Phichit", + "67" => "Phetchabun", + "70" => "Ratchaburi", + "71" => "Kanchanaburi", + "72" => "Suphan Buri", + "73" => "Nakhon Pathom", + "74" => "Samut Sakhon", + "75" => "Samut Songkhram", + "76" => "Phetchaburi", + "77" => "Prachuap Khiri Khan", + "80" => "Nakhon Si Thammarat", + "81" => "Krabi", + "82" => "Phangnga", + "83" => "Phuket", + "84" => "Surat Thani", + "85" => "Ranong", + "86" => "Chumphon", + "90" => "Songkhla", + "91" => "Satun", + "92" => "Trang", + "93" => "Phatthalung", + "94" => "Pattani", + "95" => "Yala", + "96" => "Narathiwat", + "S" => "Phatthaya" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TJ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TJ.php new file mode 100644 index 0000000..36da3cf --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TJ.php @@ -0,0 +1,11 @@ + "Tajikistan", + "subdivisions" => [ + "DU" => "Dushanbe", + "GB" => "Kŭhistoni Badakhshon", + "KT" => "Khatlon", + "RA" => "nohiyahoi tobei jumhurí", + "SU" => "Sughd" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TK.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TK.php new file mode 100644 index 0000000..d147f21 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TK.php @@ -0,0 +1,6 @@ + "Tokelau", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TL.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TL.php new file mode 100644 index 0000000..6dd0ce9 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TL.php @@ -0,0 +1,19 @@ + "Timor-Leste", + "subdivisions" => [ + "AL" => "Aileu", + "AN" => "Ainaro", + "BA" => "Baucau", + "BO" => "Bobonaro", + "CO" => "Cova Lima", + "DI" => "Díli", + "ER" => "Ermera", + "LA" => "Lautein", + "LI" => "Likisá", + "MF" => "Manufahi", + "MT" => "Manatuto", + "OE" => "Oekusi-Ambenu", + "VI" => "Vikeke" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TM.php new file mode 100644 index 0000000..671d6b8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TM.php @@ -0,0 +1,12 @@ + "Turkmenistan", + "subdivisions" => [ + "A" => "Ahal", + "B" => "Balkan", + "D" => "Daşoguz", + "L" => "Lebap", + "M" => "Mary", + "S" => "Aşgabat" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TN.php new file mode 100644 index 0000000..5eb7dbd --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TN.php @@ -0,0 +1,30 @@ + "Tunisia", + "subdivisions" => [ + "11" => "Tunis", + "12" => "L'Ariana", + "13" => "Ben Arous", + "14" => "La Manouba", + "21" => "Nabeul", + "22" => "Zaghouan", + "23" => "Bizerte", + "31" => "Béja", + "32" => "Jendouba", + "33" => "Le Kef", + "34" => "Siliana", + "41" => "Kairouan", + "42" => "Kasserine", + "43" => "Sidi Bouzid", + "51" => "Sousse", + "52" => "Monastir", + "53" => "Mahdia", + "61" => "Sfax", + "71" => "Gafsa", + "72" => "Tozeur", + "73" => "Kébili", + "81" => "Gabès", + "82" => "Médenine", + "83" => "Tataouine" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TO.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TO.php new file mode 100644 index 0000000..04334ed --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TO.php @@ -0,0 +1,11 @@ + "Tonga", + "subdivisions" => [ + "01" => "'Eua", + "02" => "Ha'apai", + "03" => "Niuas", + "04" => "Tongatapu", + "05" => "Vava'u" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TR.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TR.php new file mode 100644 index 0000000..6af25ee --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TR.php @@ -0,0 +1,87 @@ + "Türkiye", + "subdivisions" => [ + "01" => "Adana", + "02" => "Adıyaman", + "03" => "Afyonkarahisar", + "04" => "Ağrı", + "05" => "Amasya", + "06" => "Ankara", + "07" => "Antalya", + "08" => "Artvin", + "09" => "Aydın", + "10" => "Balıkesir", + "11" => "Bilecik", + "12" => "Bingöl", + "13" => "Bitlis", + "14" => "Bolu", + "15" => "Burdur", + "16" => "Bursa", + "17" => "Çanakkale", + "18" => "Çankırı", + "19" => "Çorum", + "20" => "Denizli", + "21" => "Diyarbakır", + "22" => "Edirne", + "23" => "Elazığ", + "24" => "Erzincan", + "25" => "Erzurum", + "26" => "Eskişehir", + "27" => "Gaziantep", + "28" => "Giresun", + "29" => "Gümüşhane", + "30" => "Hakkâri", + "31" => "Hatay", + "32" => "Isparta", + "33" => "Mersin", + "34" => "İstanbul", + "35" => "İzmir", + "36" => "Kars", + "37" => "Kastamonu", + "38" => "Kayseri", + "39" => "Kırklareli", + "40" => "Kırşehir", + "41" => "Kocaeli", + "42" => "Konya", + "43" => "Kütahya", + "44" => "Malatya", + "45" => "Manisa", + "46" => "Kahramanmaraş", + "47" => "Mardin", + "48" => "Muğla", + "49" => "Muş", + "50" => "Nevşehir", + "51" => "Niğde", + "52" => "Ordu", + "53" => "Rize", + "54" => "Sakarya", + "55" => "Samsun", + "56" => "Siirt", + "57" => "Sinop", + "58" => "Sivas", + "59" => "Tekirdağ", + "60" => "Tokat", + "61" => "Trabzon", + "62" => "Tunceli", + "63" => "Şanlıurfa", + "64" => "Uşak", + "65" => "Van", + "66" => "Yozgat", + "67" => "Zonguldak", + "68" => "Aksaray", + "69" => "Bayburt", + "70" => "Karaman", + "71" => "Kırıkkale", + "72" => "Batman", + "73" => "Şırnak", + "74" => "Bartın", + "75" => "Ardahan", + "76" => "Iğdır", + "77" => "Yalova", + "78" => "Karabük", + "79" => "Kilis", + "80" => "Osmaniye", + "81" => "Düzce" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TT.php new file mode 100644 index 0000000..3d34601 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TT.php @@ -0,0 +1,21 @@ + "Trinidad and Tobago", + "subdivisions" => [ + "ARI" => "Arima", + "CHA" => "Chaguanas", + "CTT" => "Couva-Tabaquite-Talparo", + "DMN" => "Diego Martin", + "MRC" => "Mayaro-Rio Claro", + "PED" => "Penal-Debe", + "POS" => "Port of Spain", + "PRT" => "Princes Town", + "PTF" => "Point Fortin", + "SFO" => "San Fernando", + "SGE" => "Sangre Grande", + "SIP" => "Siparia", + "SJL" => "San Juan-Laventille", + "TOB" => "Tobago", + "TUP" => "Tunapuna-Piarco" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TV.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TV.php new file mode 100644 index 0000000..2db0e57 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TV.php @@ -0,0 +1,14 @@ + "Tuvalu", + "subdivisions" => [ + "FUN" => "Funafuti", + "NIT" => "Niutao", + "NKF" => "Nukufetau", + "NKL" => "Nukulaelae", + "NMA" => "Nanumea", + "NMG" => "Nanumaga", + "NUI" => "Nui", + "VAI" => "Vaitupu" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TW.php new file mode 100644 index 0000000..48b7224 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TW.php @@ -0,0 +1,28 @@ + "Taiwan, Province of China", + "subdivisions" => [ + "CHA" => "Changhua", + "CYI" => "Chiayi", + "CYQ" => "Chiayi", + "HSQ" => "Hsinchu", + "HSZ" => "Hsinchu", + "HUA" => "Hualien", + "ILA" => "Yilan", + "KEE" => "Keelung", + "KHH" => "Kaohsiung", + "KIN" => "Kinmen", + "LIE" => "Lienchiang", + "MIA" => "Miaoli", + "NAN" => "Nantou", + "NWT" => "New Taipei", + "PEN" => "Penghu", + "PIF" => "Pingtung", + "TAO" => "Taoyuan", + "TNN" => "Tainan", + "TPE" => "Taipei", + "TTT" => "Taitung", + "TXG" => "Taichung", + "YUN" => "Yunlin" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/TZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/TZ.php new file mode 100644 index 0000000..6b01869 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/TZ.php @@ -0,0 +1,37 @@ + "Tanzania, United Republic of", + "subdivisions" => [ + "01" => "Arusha", + "02" => "Dar es Salaam", + "03" => "Dodoma", + "04" => "Iringa", + "05" => "Kagera", + "06" => "Pemba North", + "07" => "Zanzibar North", + "08" => "Kigoma", + "09" => "Kilimanjaro", + "10" => "Pemba South", + "11" => "Zanzibar South", + "12" => "Lindi", + "13" => "Mara", + "14" => "Mbeya", + "15" => "Zanzibar West", + "16" => "Morogoro", + "17" => "Mtwara", + "18" => "Mwanza", + "19" => "Coast", + "20" => "Rukwa", + "21" => "Ruvuma", + "22" => "Shinyanga", + "23" => "Singida", + "24" => "Tabora", + "25" => "Tanga", + "26" => "Manyara", + "27" => "Geita", + "28" => "Katavi", + "29" => "Njombe", + "30" => "Simiyu", + "31" => "Songwe" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/UA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/UA.php new file mode 100644 index 0000000..9c4d641 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/UA.php @@ -0,0 +1,33 @@ + "Ukraine", + "subdivisions" => [ + "05" => "Vinnytska oblast", + "07" => "Volynska oblast", + "09" => "Luhanska oblast", + "12" => "Dnipropetrovska oblast", + "14" => "Donetska oblast", + "18" => "Zhytomyrska oblast", + "21" => "Zakarpatska oblast", + "23" => "Zaporizka oblast", + "26" => "Ivano-Frankivska oblast", + "30" => "Kyiv", + "32" => "Kyivska oblast", + "35" => "Kirovohradska oblast", + "40" => "Sevastopol", + "43" => "Avtonomna Respublika Krym", + "46" => "Lvivska oblast", + "48" => "Mykolaivska oblast", + "51" => "Odeska oblast", + "53" => "Poltavska oblast", + "56" => "Rivnenska oblast", + "59" => "Sumska oblast", + "61" => "Ternopilska oblast", + "63" => "Kharkivska oblast", + "65" => "Khersonska oblast", + "68" => "Khmelnytska oblast", + "71" => "Cherkaska oblast", + "74" => "Chernihivska oblast", + "77" => "Chernivetska oblast" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/UG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/UG.php new file mode 100644 index 0000000..e8b0774 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/UG.php @@ -0,0 +1,145 @@ + "Uganda", + "subdivisions" => [ + "101" => "Kalangala", + "102" => "Kampala", + "103" => "Kiboga", + "104" => "Luwero", + "105" => "Masaka", + "106" => "Mpigi", + "107" => "Mubende", + "108" => "Mukono", + "109" => "Nakasongola", + "110" => "Rakai", + "111" => "Sembabule", + "112" => "Kayunga", + "113" => "Wakiso", + "114" => "Lyantonde", + "115" => "Mityana", + "116" => "Nakaseke", + "117" => "Buikwe", + "118" => "Bukomansibi", + "119" => "Butambala", + "120" => "Buvuma", + "121" => "Gomba", + "122" => "Kalungu", + "123" => "Kyankwanzi", + "124" => "Lwengo", + "125" => "Kyotera", + "126" => "Kasanda", + "201" => "Bugiri", + "202" => "Busia", + "203" => "Iganga", + "204" => "Jinja", + "205" => "Kamuli", + "206" => "Kapchorwa", + "207" => "Katakwi", + "208" => "Kumi", + "209" => "Mbale", + "210" => "Pallisa", + "211" => "Soroti", + "212" => "Tororo", + "213" => "Kaberamaido", + "214" => "Mayuge", + "215" => "Sironko", + "216" => "Amuria", + "217" => "Budaka", + "218" => "Bududa", + "219" => "Bukedea", + "220" => "Bukwo", + "221" => "Butaleja", + "222" => "Kaliro", + "223" => "Manafwa", + "224" => "Namutumba", + "225" => "Bulambuli", + "226" => "Buyende", + "227" => "Kibuku", + "228" => "Kween", + "229" => "Luuka", + "230" => "Namayingo", + "231" => "Ngora", + "232" => "Serere", + "233" => "Butebo", + "234" => "Namisindwa", + "235" => "Bugweri", + "236" => "Kapelebyong", + "237" => "Kalaki", + "301" => "Adjumani", + "302" => "Apac", + "303" => "Arua", + "304" => "Gulu", + "305" => "Kitgum", + "306" => "Kotido", + "307" => "Lira", + "308" => "Moroto", + "309" => "Moyo", + "310" => "Nebbi", + "311" => "Nakapiripirit", + "312" => "Pader", + "313" => "Yumbe", + "314" => "Abim", + "315" => "Amolatar", + "316" => "Amuru", + "317" => "Dokolo", + "318" => "Kaabong", + "319" => "Koboko", + "320" => "Maracha", + "321" => "Oyam", + "322" => "Agago", + "323" => "Alebtong", + "324" => "Amudat", + "325" => "Kole", + "326" => "Lamwo", + "327" => "Napak", + "328" => "Nwoya", + "329" => "Otuke", + "330" => "Zombo", + "331" => "Omoro", + "332" => "Pakwach", + "333" => "Kwania", + "334" => "Nabilatuk", + "335" => "Karenga", + "336" => "Madi-Okollo", + "337" => "Obongi", + "401" => "Bundibugyo", + "402" => "Bushenyi", + "403" => "Hoima", + "404" => "Kabale", + "405" => "Kabarole", + "406" => "Kasese", + "407" => "Kibaale", + "408" => "Kisoro", + "409" => "Masindi", + "410" => "Mbarara", + "411" => "Ntungamo", + "412" => "Rukungiri", + "413" => "Kamwenge", + "414" => "Kanungu", + "415" => "Kyenjojo", + "416" => "Buliisa", + "417" => "Ibanda", + "418" => "Isingiro", + "419" => "Kiruhura", + "420" => "Buhweju", + "421" => "Kiryandongo", + "422" => "Kyegegwa", + "423" => "Mitooma", + "424" => "Ntoroko", + "425" => "Rubirizi", + "426" => "Sheema", + "427" => "Kagadi", + "428" => "Kakumiro", + "429" => "Rubanda", + "430" => "Bunyangabu", + "431" => "Rukiga", + "432" => "Kikuube", + "433" => "Kazo", + "434" => "Kitagwenda", + "435" => "Rwampara", + "C" => "Central", + "E" => "Eastern", + "N" => "Northern", + "W" => "Western" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/UM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/UM.php new file mode 100644 index 0000000..3cf5f59 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/UM.php @@ -0,0 +1,15 @@ + "United States Minor Outlying Islands", + "subdivisions" => [ + "67" => "Johnston Atoll", + "71" => "Midway Islands", + "76" => "Navassa Island", + "79" => "Wake Island", + "81" => "Baker Island", + "84" => "Howland Island", + "86" => "Jarvis Island", + "89" => "Kingman Reef", + "95" => "Palmyra Atoll" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/US.php b/cacme/vendor/workerman/validation/data/iso_3166-2/US.php new file mode 100644 index 0000000..06e7042 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/US.php @@ -0,0 +1,63 @@ + "United States", + "subdivisions" => [ + "AK" => "Alaska", + "AL" => "Alabama", + "AR" => "Arkansas", + "AS" => "American Samoa", + "AZ" => "Arizona", + "CA" => "California", + "CO" => "Colorado", + "CT" => "Connecticut", + "DC" => "District of Columbia", + "DE" => "Delaware", + "FL" => "Florida", + "GA" => "Georgia", + "GU" => "Guam", + "HI" => "Hawaii", + "IA" => "Iowa", + "ID" => "Idaho", + "IL" => "Illinois", + "IN" => "Indiana", + "KS" => "Kansas", + "KY" => "Kentucky", + "LA" => "Louisiana", + "MA" => "Massachusetts", + "MD" => "Maryland", + "ME" => "Maine", + "MI" => "Michigan", + "MN" => "Minnesota", + "MO" => "Missouri", + "MP" => "Northern Mariana Islands", + "MS" => "Mississippi", + "MT" => "Montana", + "NC" => "North Carolina", + "ND" => "North Dakota", + "NE" => "Nebraska", + "NH" => "New Hampshire", + "NJ" => "New Jersey", + "NM" => "New Mexico", + "NV" => "Nevada", + "NY" => "New York", + "OH" => "Ohio", + "OK" => "Oklahoma", + "OR" => "Oregon", + "PA" => "Pennsylvania", + "PR" => "Puerto Rico", + "RI" => "Rhode Island", + "SC" => "South Carolina", + "SD" => "South Dakota", + "TN" => "Tennessee", + "TX" => "Texas", + "UM" => "United States Minor Outlying Islands", + "UT" => "Utah", + "VA" => "Virginia", + "VI" => "Virgin Islands, U.S.", + "VT" => "Vermont", + "WA" => "Washington", + "WI" => "Wisconsin", + "WV" => "West Virginia", + "WY" => "Wyoming" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/UY.php b/cacme/vendor/workerman/validation/data/iso_3166-2/UY.php new file mode 100644 index 0000000..72e35e8 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/UY.php @@ -0,0 +1,25 @@ + "Uruguay", + "subdivisions" => [ + "AR" => "Artigas", + "CA" => "Canelones", + "CL" => "Cerro Largo", + "CO" => "Colonia", + "DU" => "Durazno", + "FD" => "Florida", + "FS" => "Flores", + "LA" => "Lavalleja", + "MA" => "Maldonado", + "MO" => "Montevideo", + "PA" => "Paysandú", + "RN" => "Río Negro", + "RO" => "Rocha", + "RV" => "Rivera", + "SA" => "Salto", + "SJ" => "San José", + "SO" => "Soriano", + "TA" => "Tacuarembó", + "TT" => "Treinta y Tres" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/UZ.php b/cacme/vendor/workerman/validation/data/iso_3166-2/UZ.php new file mode 100644 index 0000000..750d74d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/UZ.php @@ -0,0 +1,20 @@ + "Uzbekistan", + "subdivisions" => [ + "AN" => "Andijon", + "BU" => "Buxoro", + "FA" => "Farg‘ona", + "JI" => "Jizzax", + "NG" => "Namangan", + "NW" => "Navoiy", + "QA" => "Qashqadaryo", + "QR" => "Qoraqalpog‘iston Respublikasi", + "SA" => "Samarqand", + "SI" => "Sirdaryo", + "SU" => "Surxondaryo", + "TK" => "Toshkent", + "TO" => "Toshkent", + "XO" => "Xorazm" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VA.php new file mode 100644 index 0000000..a7e0031 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VA.php @@ -0,0 +1,6 @@ + "Holy See (Vatican City State)", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VC.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VC.php new file mode 100644 index 0000000..2e7bf97 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VC.php @@ -0,0 +1,12 @@ + "Saint Vincent and the Grenadines", + "subdivisions" => [ + "01" => "Charlotte", + "02" => "Saint Andrew", + "03" => "Saint David", + "04" => "Saint George", + "05" => "Saint Patrick", + "06" => "Grenadines" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VE.php new file mode 100644 index 0000000..3598656 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VE.php @@ -0,0 +1,31 @@ + "Venezuela, Bolivarian Republic of", + "subdivisions" => [ + "A" => "Distrito Capital", + "B" => "Anzoátegui", + "C" => "Apure", + "D" => "Aragua", + "E" => "Barinas", + "F" => "Bolívar", + "G" => "Carabobo", + "H" => "Cojedes", + "I" => "Falcón", + "J" => "Guárico", + "K" => "Lara", + "L" => "Mérida", + "M" => "Miranda", + "N" => "Monagas", + "O" => "Nueva Esparta", + "P" => "Portuguesa", + "R" => "Sucre", + "S" => "Táchira", + "T" => "Trujillo", + "U" => "Yaracuy", + "V" => "Zulia", + "W" => "Dependencias Federales", + "X" => "La Guaira", + "Y" => "Delta Amacuro", + "Z" => "Amazonas" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VG.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VG.php new file mode 100644 index 0000000..8be7c0c --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VG.php @@ -0,0 +1,6 @@ + "Virgin Islands, British", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VI.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VI.php new file mode 100644 index 0000000..41096e3 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VI.php @@ -0,0 +1,6 @@ + "Virgin Islands, U.S.", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VN.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VN.php new file mode 100644 index 0000000..917b686 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VN.php @@ -0,0 +1,69 @@ + "Viet Nam", + "subdivisions" => [ + "01" => "Lai Châu", + "02" => "Lào Cai", + "03" => "Hà Giang", + "04" => "Cao Bằng", + "05" => "Sơn La", + "06" => "Yên Bái", + "07" => "Tuyên Quang", + "09" => "Lạng Sơn", + "13" => "Quảng Ninh", + "14" => "Hòa Bình", + "18" => "Ninh Bình", + "20" => "Thái Bình", + "21" => "Thanh Hóa", + "22" => "Nghệ An", + "23" => "Hà Tĩnh", + "24" => "Quảng Bình", + "25" => "Quảng Trị", + "26" => "Thừa Thiên-Huế", + "27" => "Quảng Nam", + "28" => "Kon Tum", + "29" => "Quảng Ngãi", + "30" => "Gia Lai", + "31" => "Bình Định", + "32" => "Phú Yên", + "33" => "Đắk Lắk", + "34" => "Khánh Hòa", + "35" => "Lâm Đồng", + "36" => "Ninh Thuận", + "37" => "Tây Ninh", + "39" => "Đồng Nai", + "40" => "Bình Thuận", + "41" => "Long An", + "43" => "Bà Rịa - Vũng Tàu", + "44" => "An Giang", + "45" => "Đồng Tháp", + "46" => "Tiền Giang", + "47" => "Kiến Giang", + "49" => "Vĩnh Long", + "50" => "Bến Tre", + "51" => "Trà Vinh", + "52" => "Sóc Trăng", + "53" => "Bắc Kạn", + "54" => "Bắc Giang", + "55" => "Bạc Liêu", + "56" => "Bắc Ninh", + "57" => "Bình Dương", + "58" => "Bình Phước", + "59" => "Cà Mau", + "61" => "Hải Dương", + "63" => "Hà Nam", + "66" => "Hưng Yên", + "67" => "Nam Định", + "68" => "Phú Thọ", + "69" => "Thái Nguyên", + "70" => "Vĩnh Phúc", + "71" => "Điện Biên", + "72" => "Đắk Nông", + "73" => "Hậu Giang", + "CT" => "Cần Thơ", + "DN" => "Đà Nẵng", + "HN" => "Hà Nội", + "HP" => "Hải Phòng", + "SG" => "Hồ Chí Minh" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/VU.php b/cacme/vendor/workerman/validation/data/iso_3166-2/VU.php new file mode 100644 index 0000000..41a57be --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/VU.php @@ -0,0 +1,12 @@ + "Vanuatu", + "subdivisions" => [ + "MAP" => "Malampa", + "PAM" => "Pénama", + "SAM" => "Sanma", + "SEE" => "Shéfa", + "TAE" => "Taféa", + "TOB" => "Torba" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/WF.php b/cacme/vendor/workerman/validation/data/iso_3166-2/WF.php new file mode 100644 index 0000000..d29bbc4 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/WF.php @@ -0,0 +1,9 @@ + "Wallis and Futuna", + "subdivisions" => [ + "AL" => "Alo", + "SG" => "Sigave", + "UV" => "Uvea" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/WS.php b/cacme/vendor/workerman/validation/data/iso_3166-2/WS.php new file mode 100644 index 0000000..b5cb4b7 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/WS.php @@ -0,0 +1,17 @@ + "Samoa", + "subdivisions" => [ + "AA" => "A'ana", + "AL" => "Aiga-i-le-Tai", + "AT" => "Atua", + "FA" => "Fa'asaleleaga", + "GE" => "Gaga'emauga", + "GI" => "Gagaifomauga", + "PA" => "Palauli", + "SA" => "Satupa'itea", + "TU" => "Tuamasaga", + "VF" => "Va'a-o-Fonoti", + "VS" => "Vaisigano" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/YE.php b/cacme/vendor/workerman/validation/data/iso_3166-2/YE.php new file mode 100644 index 0000000..c781874 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/YE.php @@ -0,0 +1,28 @@ + "Yemen", + "subdivisions" => [ + "AB" => "Abyan", + "AD" => "‘Adan", + "AM" => "‘Amrān", + "BA" => "Al Bayḑā’", + "DA" => "Aḑ Ḑāli‘", + "DH" => "Dhamār", + "HD" => "Ḩaḑramawt", + "HJ" => "Ḩajjah", + "HU" => "Al Ḩudaydah", + "IB" => "Ibb", + "JA" => "Al Jawf", + "LA" => "Laḩij", + "MA" => "Ma’rib", + "MR" => "Al Mahrah", + "MW" => "Al Maḩwīt", + "RA" => "Raymah", + "SA" => "Amānat al ‘Āşimah [city]", + "SD" => "Şāʻdah", + "SH" => "Shabwah", + "SN" => "Şanʻā’", + "SU" => "Arkhabīl Suquţrá", + "TA" => "Tāʻizz" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/YT.php b/cacme/vendor/workerman/validation/data/iso_3166-2/YT.php new file mode 100644 index 0000000..700a72d --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/YT.php @@ -0,0 +1,6 @@ + "Mayotte", + "subdivisions" => [ + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ZA.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ZA.php new file mode 100644 index 0000000..e1eb379 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ZA.php @@ -0,0 +1,15 @@ + "South Africa", + "subdivisions" => [ + "EC" => "Eastern Cape", + "FS" => "Free State", + "GP" => "Gauteng", + "KZN" => "Kwazulu-Natal", + "LP" => "Limpopo", + "MP" => "Mpumalanga", + "NC" => "Northern Cape", + "NW" => "North-West", + "WC" => "Western Cape" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ZM.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ZM.php new file mode 100644 index 0000000..b08c5ba --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ZM.php @@ -0,0 +1,16 @@ + "Zambia", + "subdivisions" => [ + "01" => "Western", + "02" => "Central", + "03" => "Eastern", + "04" => "Luapula", + "05" => "Northern", + "06" => "North-Western", + "07" => "Southern", + "08" => "Copperbelt", + "09" => "Lusaka", + "10" => "Muchinga" + ] +]; diff --git a/cacme/vendor/workerman/validation/data/iso_3166-2/ZW.php b/cacme/vendor/workerman/validation/data/iso_3166-2/ZW.php new file mode 100644 index 0000000..173ba66 --- /dev/null +++ b/cacme/vendor/workerman/validation/data/iso_3166-2/ZW.php @@ -0,0 +1,16 @@ + "Zimbabwe", + "subdivisions" => [ + "BU" => "Bulawayo", + "HA" => "Harare", + "MA" => "Manicaland", + "MC" => "Mashonaland Central", + "ME" => "Mashonaland East", + "MI" => "Midlands", + "MN" => "Matabeleland North", + "MS" => "Matabeleland South", + "MV" => "Masvingo", + "MW" => "Mashonaland West" + ] +]; diff --git a/cacme/vendor/workerman/validation/library/ChainedValidator.php b/cacme/vendor/workerman/validation/library/ChainedValidator.php new file mode 100644 index 0000000..a45e2fd --- /dev/null +++ b/cacme/vendor/workerman/validation/library/ChainedValidator.php @@ -0,0 +1,377 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation; + +use finfo; +use Respect\Validation\Rules\Key; + +interface ChainedValidator extends Validatable +{ + public function allOf(Validatable ...$rule): ChainedValidator; + + public function alnum(string ...$additionalChars): ChainedValidator; + + public function alpha(string ...$additionalChars): ChainedValidator; + + public function alwaysInvalid(): ChainedValidator; + + public function alwaysValid(): ChainedValidator; + + public function anyOf(Validatable ...$rule): ChainedValidator; + + public function arrayType(): ChainedValidator; + + public function arrayVal(): ChainedValidator; + + public function attribute( + string $reference, + ?Validatable $validator = null, + bool $mandatory = true + ): ChainedValidator; + + public function base(int $base, ?string $chars = null): ChainedValidator; + + public function base64(): ChainedValidator; + + /** + * @param mixed $minimum + * @param mixed $maximum + */ + public function between($minimum, $maximum): ChainedValidator; + + public function boolType(): ChainedValidator; + + public function boolVal(): ChainedValidator; + + public function bsn(): ChainedValidator; + + public function call(callable $callable, Validatable $rule): ChainedValidator; + + public function callableType(): ChainedValidator; + + public function callback(callable $callback): ChainedValidator; + + public function charset(string ...$charset): ChainedValidator; + + public function cnh(): ChainedValidator; + + public function cnpj(): ChainedValidator; + + public function control(string ...$additionalChars): ChainedValidator; + + public function consonant(string ...$additionalChars): ChainedValidator; + + /** + * @param mixed $containsValue + */ + public function contains($containsValue, bool $identical = false): ChainedValidator; + + /** + * @param mixed[] $needles + */ + public function containsAny(array $needles, bool $strictCompareArray = false): ChainedValidator; + + public function countable(): ChainedValidator; + + public function countryCode(?string $set = null): ChainedValidator; + + public function currencyCode(): ChainedValidator; + + public function cpf(): ChainedValidator; + + public function creditCard(?string $brand = null): ChainedValidator; + + public function date(string $format = 'Y-m-d'): ChainedValidator; + + public function dateTime(?string $format = null): ChainedValidator; + + public function decimal(int $decimals): ChainedValidator; + + public function digit(string ...$additionalChars): ChainedValidator; + + public function directory(): ChainedValidator; + + public function domain(bool $tldCheck = true): ChainedValidator; + + public function each(Validatable $rule): ChainedValidator; + + public function email(): ChainedValidator; + + /** + * @param mixed $endValue + */ + public function endsWith($endValue, bool $identical = false): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function equals($compareTo): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function equivalent($compareTo): ChainedValidator; + + public function even(): ChainedValidator; + + public function executable(): ChainedValidator; + + public function exists(): ChainedValidator; + + public function extension(string $extension): ChainedValidator; + + public function factor(int $dividend): ChainedValidator; + + public function falseVal(): ChainedValidator; + + public function fibonacci(): ChainedValidator; + + public function file(): ChainedValidator; + + /** + * @param mixed[]|int $options + */ + public function filterVar(int $filter, $options = null): ChainedValidator; + + public function finite(): ChainedValidator; + + public function floatVal(): ChainedValidator; + + public function floatType(): ChainedValidator; + + public function graph(string ...$additionalChars): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function greaterThan($compareTo): ChainedValidator; + + public function hexRgbColor(): ChainedValidator; + + public function iban(): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function identical($compareTo): ChainedValidator; + + public function image(?finfo $fileInfo = null): ChainedValidator; + + public function imei(): ChainedValidator; + + /** + * @param mixed[]|mixed $haystack + */ + public function in($haystack, bool $compareIdentical = false): ChainedValidator; + + public function infinite(): ChainedValidator; + + public function instance(string $instanceName): ChainedValidator; + + public function intVal(): ChainedValidator; + + public function intType(): ChainedValidator; + + public function ip(string $range = '*', ?int $options = null): ChainedValidator; + + public function isbn(): ChainedValidator; + + public function iterableType(): ChainedValidator; + + public function json(): ChainedValidator; + + public function key( + string $reference, + ?Validatable $referenceValidator = null, + bool $mandatory = true + ): ChainedValidator; + + public function keyNested( + string $reference, + ?Validatable $referenceValidator = null, + bool $mandatory = true + ): ChainedValidator; + + public function keySet(Key ...$rule): ChainedValidator; + + public function keyValue(string $comparedKey, string $ruleName, string $baseKey): ChainedValidator; + + public function languageCode(?string $set = null): ChainedValidator; + + public function leapDate(string $format): ChainedValidator; + + public function leapYear(): ChainedValidator; + + public function length(?int $min = null, ?int $max = null, bool $inclusive = true): ChainedValidator; + + public function lowercase(): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function lessThan($compareTo): ChainedValidator; + + public function luhn(): ChainedValidator; + + public function macAddress(): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function max($compareTo): ChainedValidator; + + public function maxAge(int $age, ?string $format = null): ChainedValidator; + + public function mimetype(string $mimetype): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public function min($compareTo): ChainedValidator; + + public function minAge(int $age, ?string $format = null): ChainedValidator; + + public function multiple(int $multipleOf): ChainedValidator; + + public function negative(): ChainedValidator; + + public function nfeAccessKey(): ChainedValidator; + + public function nif(): ChainedValidator; + + public function nip(): ChainedValidator; + + public function no(bool $useLocale = false): ChainedValidator; + + public function noneOf(Validatable ...$rule): ChainedValidator; + + public function not(Validatable $rule): ChainedValidator; + + public function notBlank(): ChainedValidator; + + public function notEmoji(): ChainedValidator; + + public function notEmpty(): ChainedValidator; + + public function notOptional(): ChainedValidator; + + public function noWhitespace(): ChainedValidator; + + public function nullable(Validatable $rule): ChainedValidator; + + public function nullType(): ChainedValidator; + + public function number(): ChainedValidator; + + public function numericVal(): ChainedValidator; + + public function objectType(): ChainedValidator; + + public function odd(): ChainedValidator; + + public function oneOf(Validatable ...$rule): ChainedValidator; + + public function optional(Validatable $rule): ChainedValidator; + + public function perfectSquare(): ChainedValidator; + + public function pesel(): ChainedValidator; + + public function phone(): ChainedValidator; + + public function mobile(): ChainedValidator; + public function phpLabel(): ChainedValidator; + + public function pis(): ChainedValidator; + + public function polishIdCard(): ChainedValidator; + + public function portugueseNif(): ChainedValidator; + + public function positive(): ChainedValidator; + + public function postalCode(string $countryCode): ChainedValidator; + + public function primeNumber(): ChainedValidator; + + public function printable(string ...$additionalChars): ChainedValidator; + + public function publicDomainSuffix(): ChainedValidator; + + public function punct(string ...$additionalChars): ChainedValidator; + + public function readable(): ChainedValidator; + + public function regex(string $regex): ChainedValidator; + + public function resourceType(): ChainedValidator; + + public function roman(): ChainedValidator; + + public function scalarVal(): ChainedValidator; + + public function size(?string $minSize = null, ?string $maxSize = null): ChainedValidator; + + public function slug(): ChainedValidator; + + public function sorted(string $direction): ChainedValidator; + + public function space(string ...$additionalChars): ChainedValidator; + + /** + * @param mixed $startValue + */ + public function startsWith($startValue, bool $identical = false): ChainedValidator; + + public function stringType(): ChainedValidator; + + public function stringVal(): ChainedValidator; + + public function subdivisionCode(string $countryCode): ChainedValidator; + + /** + * @param mixed[] $superset + */ + public function subset(array $superset): ChainedValidator; + + public function symbolicLink(): ChainedValidator; + + public function time(string $format = 'H:i:s'): ChainedValidator; + + public function tld(): ChainedValidator; + + public function trueVal(): ChainedValidator; + + public function type(string $type): ChainedValidator; + + public function unique(): ChainedValidator; + + public function uploaded(): ChainedValidator; + + public function uppercase(): ChainedValidator; + + public function url(): ChainedValidator; + + public function uuid(?int $version = null): ChainedValidator; + + public function version(): ChainedValidator; + + public function videoUrl(?string $service = null): ChainedValidator; + + public function vowel(string ...$additionalChars): ChainedValidator; + + public function when(Validatable $if, Validatable $then, ?Validatable $else = null): ChainedValidator; + + public function writable(): ChainedValidator; + + public function xdigit(string ...$additionalChars): ChainedValidator; + + public function yes(bool $useLocale = false): ChainedValidator; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AllOfException.php b/cacme/vendor/workerman/validation/library/Exceptions/AllOfException.php new file mode 100644 index 0000000..2072308 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AllOfException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +class AllOfException extends GroupedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::NONE => '{{name}} 必需符合以下规则', + self::SOME => '{{name}} 必需符合以下规则', + ], + self::MODE_NEGATIVE => [ + self::NONE => '{{name}} 不能符合以下规则', + self::SOME => '{{name}} 不能符合以下规则', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AlnumException.php b/cacme/vendor/workerman/validation/library/Exceptions/AlnumException.php new file mode 100644 index 0000000..da72816 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AlnumException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class AlnumException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含字母(a-z)和数字(0-9)', + self::EXTRA => '{{name}} 只能包含字母(a-z)、数字(0-9)和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含字母(a-z)或数字(0-9)', + self::EXTRA => '{{name}} 不能包含字母(a-z)、数字(0-9)或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AlphaException.php b/cacme/vendor/workerman/validation/library/Exceptions/AlphaException.php new file mode 100644 index 0000000..c29833f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AlphaException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class AlphaException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含字母(a-z)', + self::EXTRA => '{{name}} 只能包含字母(a-z)和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含字母(a-z)', + self::EXTRA => '{{name}} 不能包含字母(a-z)或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AlwaysInvalidException.php b/cacme/vendor/workerman/validation/library/Exceptions/AlwaysInvalidException.php new file mode 100644 index 0000000..70bd71b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AlwaysInvalidException.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class AlwaysInvalidException extends ValidationException +{ + public const SIMPLE = 'simple'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 始终无效', + self::SIMPLE => '{{name}} 无效', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 始终有效', + self::SIMPLE => '{{name}} 有效', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AlwaysValidException.php b/cacme/vendor/workerman/validation/library/Exceptions/AlwaysValidException.php new file mode 100644 index 0000000..e38a176 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AlwaysValidException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class AlwaysValidException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 始终有效', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 始终无效', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AnyOfException.php b/cacme/vendor/workerman/validation/library/Exceptions/AnyOfException.php new file mode 100644 index 0000000..c7f7246 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AnyOfException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class AnyOfException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '这些规则中至少有一个必须传递给 {{name}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '这些规则中至少有一个不能传递给 {{name}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ArrayTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/ArrayTypeException.php new file mode 100644 index 0000000..2544588 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ArrayTypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + * @author João Torquato + */ +final class ArrayTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是array类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是array类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ArrayValException.php b/cacme/vendor/workerman/validation/library/Exceptions/ArrayValException.php new file mode 100644 index 0000000..a4bf796 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ArrayValException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class ArrayValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是数组', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是数组', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/AttributeException.php b/cacme/vendor/workerman/validation/library/Exceptions/AttributeException.php new file mode 100644 index 0000000..9aaf4e0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/AttributeException.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions to be thrown by the Attribute Rule. + * + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class AttributeException extends NestedValidationException implements NonOmissibleException +{ + public const NOT_PRESENT = 'not_present'; + public const INVALID = 'invalid'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::NOT_PRESENT => '属性 {{name}} 必须存在', + self::INVALID => '属性 {{name}} 必须有效', + ], + self::MODE_NEGATIVE => [ + self::NOT_PRESENT => '属性 {{name}} 不能存在', + self::INVALID => '属性 {{name}} 必须无效', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + return $this->getParam('hasReference') ? self::INVALID : self::NOT_PRESENT; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/Base64Exception.php b/cacme/vendor/workerman/validation/library/Exceptions/Base64Exception.php new file mode 100644 index 0000000..ac29a3d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/Base64Exception.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Jens Segers + * @author William Espindola + */ +final class Base64Exception extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须采用Base64编码', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是Base64编码', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/BaseException.php b/cacme/vendor/workerman/validation/library/Exceptions/BaseException.php new file mode 100644 index 0000000..e4b929f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/BaseException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Carlos André Ferrari + * @author Henrique Moody + * @author William Espindola + */ +final class BaseException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是基于 {{base}} 中的数字', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是基于 {{base}} 中的数字', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/BetweenException.php b/cacme/vendor/workerman/validation/library/Exceptions/BetweenException.php new file mode 100644 index 0000000..066132f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/BetweenException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class BetweenException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须介于 {{minValue}} 和 {{maxValue}} 之间', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能介于 {{minValue}} 和 {{maxValue}} 之间', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/BoolTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/BoolTypeException.php new file mode 100644 index 0000000..c748ea3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/BoolTypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for BoolType rule. + * + * @author Devin Torres + * @author Henrique Moody + */ +final class BoolTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是boolean类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是boolean类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/BoolValException.php b/cacme/vendor/workerman/validation/library/Exceptions/BoolValException.php new file mode 100644 index 0000000..7fd23de --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/BoolValException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Emmerson Siqueira + * @author Henrique Moody + * @author William Espindola + */ +final class BoolValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是布尔值', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是布尔值', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/BsnException.php b/cacme/vendor/workerman/validation/library/Exceptions/BsnException.php new file mode 100644 index 0000000..57278f1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/BsnException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Ronald Drenth + * @author William Espindola + */ +final class BsnException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是BSN', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是BSN', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CallException.php b/cacme/vendor/workerman/validation/library/Exceptions/CallException.php new file mode 100644 index 0000000..68b7b06 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CallException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class CallException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '当使用 {{callable}} 时 {{input}} 必须有效', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '当使用 {{callable}} 时 {{input}} 必须无效', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CallableTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/CallableTypeException.php new file mode 100644 index 0000000..bdd7fbe --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CallableTypeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for CallableType rule. + * + * @author Henrique Moody + */ +final class CallableTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是可调用的', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是可调用的', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CallbackException.php b/cacme/vendor/workerman/validation/library/Exceptions/CallbackException.php new file mode 100644 index 0000000..548ee14 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CallbackException.php @@ -0,0 +1,19 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class CallbackException extends NestedValidationException +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CharsetException.php b/cacme/vendor/workerman/validation/library/Exceptions/CharsetException.php new file mode 100644 index 0000000..6182c3a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CharsetException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class CharsetException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须在 {{charset}} 字符集中', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能在 {{charset}} 字符集中', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CnhException.php b/cacme/vendor/workerman/validation/library/Exceptions/CnhException.php new file mode 100644 index 0000000..692188a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CnhException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Kinn Coelho Julião + * @author William Espindola + */ +final class CnhException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的CNH号码', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的CNH号码', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CnpjException.php b/cacme/vendor/workerman/validation/library/Exceptions/CnpjException.php new file mode 100644 index 0000000..7eaf67d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CnpjException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Leonn Leite + * @author William Espindola + */ +final class CnpjException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的CNPJ编号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的CNPJ编号', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ComponentException.php b/cacme/vendor/workerman/validation/library/Exceptions/ComponentException.php new file mode 100644 index 0000000..dd252a9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ComponentException.php @@ -0,0 +1,21 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use Exception; +use Throwable; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +class ComponentException extends Exception implements Throwable +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ConsonantException.php b/cacme/vendor/workerman/validation/library/Exceptions/ConsonantException.php new file mode 100644 index 0000000..3aa7bca --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ConsonantException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Danilo Correa + * @author Kleber Hamada Sato + */ +final class ConsonantException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含辅音', + self::EXTRA => '{{name}} 只能包含辅音和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含辅音', + self::EXTRA => '{{name}} 不能包含辅音或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ContainsAnyException.php b/cacme/vendor/workerman/validation/library/Exceptions/ContainsAnyException.php new file mode 100644 index 0000000..67572d3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ContainsAnyException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Kirill Dlussky + */ +final class ContainsAnyException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须包含至少一个值 {{needles}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含任何值 {{needles}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ContainsException.php b/cacme/vendor/workerman/validation/library/Exceptions/ContainsException.php new file mode 100644 index 0000000..3d31bb1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ContainsException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class ContainsException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须包含值 {{containsValue}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含值 {{containsValue}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ControlException.php b/cacme/vendor/workerman/validation/library/Exceptions/ControlException.php new file mode 100644 index 0000000..4c5f86b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ControlException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + */ +final class ControlException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含控制字符', + self::EXTRA => '{{name}} 只能包含控制字符和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含控制字符', + self::EXTRA => '{{name}} 不能包含控制字符或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CountableException.php b/cacme/vendor/workerman/validation/library/Exceptions/CountableException.php new file mode 100644 index 0000000..aeaec42 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CountableException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author João Torquato + * @author William Espindola + */ +final class CountableException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是可数的', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是可数的', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CountryCodeException.php b/cacme/vendor/workerman/validation/library/Exceptions/CountryCodeException.php new file mode 100644 index 0000000..4fb9b2d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CountryCodeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class CountryCodeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的国家/地区', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的国家/地区', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CpfException.php b/cacme/vendor/workerman/validation/library/Exceptions/CpfException.php new file mode 100644 index 0000000..671e899 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CpfException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Jair Henrique + * @author William Espindola + */ +final class CpfException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的CPF编号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的CPF编号', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CreditCardException.php b/cacme/vendor/workerman/validation/library/Exceptions/CreditCardException.php new file mode 100644 index 0000000..a60ef3b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CreditCardException.php @@ -0,0 +1,48 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use Respect\Validation\Rules\CreditCard; + +/** + * @author Henrique Moody + * @author Jean Pimentel + * @author William Espindola + */ +final class CreditCardException extends ValidationException +{ + public const BRANDED = 'branded'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的信用卡号', + self::BRANDED => '{{name}} 必须是有效的 {{brand}} 信用卡号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的信用卡号', + self::BRANDED => '{{name}} 不能是有效的 {{brand}} 信用卡号', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('brand') === CreditCard::ANY) { + return self::STANDARD; + } + + return self::BRANDED; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/CurrencyCodeException.php b/cacme/vendor/workerman/validation/library/Exceptions/CurrencyCodeException.php new file mode 100644 index 0000000..7d4c75f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/CurrencyCodeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Justin Hook + * @author William Espindola + */ +final class CurrencyCodeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的货币', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的货币', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/DateException.php b/cacme/vendor/workerman/validation/library/Exceptions/DateException.php new file mode 100644 index 0000000..86d7c66 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/DateException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Bruno Luiz da Silva + * @author Henrique Moody + */ +final class DateException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是格式为 {{sample}} 的有效日期', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是格式为 {{sample}} 的日期', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/DateTimeException.php b/cacme/vendor/workerman/validation/library/Exceptions/DateTimeException.php new file mode 100644 index 0000000..44a6619 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/DateTimeException.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class DateTimeException extends ValidationException +{ + public const FORMAT = 'format'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的日期/时间', + self::FORMAT => '{{name}} 必须是格式为 {{sample}} 的有效日期/时间', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的日期/时间', + self::FORMAT => '{{name}} 不能是格式为 {{sample}} 的有效日期/时间', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + return $this->getParam('format') ? self::FORMAT : self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/DecimalException.php b/cacme/vendor/workerman/validation/library/Exceptions/DecimalException.php new file mode 100644 index 0000000..69cf14d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/DecimalException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class DecimalException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} must have {{decimals}} decimals', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} must not have {{decimals}} decimals', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/DigitException.php b/cacme/vendor/workerman/validation/library/Exceptions/DigitException.php new file mode 100644 index 0000000..d52c1d1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/DigitException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class DigitException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含数字(0-9)', + self::EXTRA => '{{name}} 只能包含数字(0-9)和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含数字(0-9)', + self::EXTRA => '{{name}} 只能包含数字(0-9)和 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/DirectoryException.php b/cacme/vendor/workerman/validation/library/Exceptions/DirectoryException.php new file mode 100644 index 0000000..3b435ae --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/DirectoryException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author William Espindola + */ +final class DirectoryException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是目录', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是目录', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/DomainException.php b/cacme/vendor/workerman/validation/library/Exceptions/DomainException.php new file mode 100644 index 0000000..5656a63 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/DomainException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class DomainException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效域名', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效域名', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/EachException.php b/cacme/vendor/workerman/validation/library/Exceptions/EachException.php new file mode 100644 index 0000000..ece4c43 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/EachException.php @@ -0,0 +1,52 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class EachException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 中的每个项都必须有效', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 中的每个项都必须无效', + ], + ]; + + /** + * {@inheritDoc} + * + * @todo This method shares too much with the parent implementation + */ + public function getMessages(array $templates = []): array + { + $messages = []; + $count = -1; + foreach ($this->getChildren() as $exception) { + $count++; + $id = $exception->getId(); + + $messages[$id . '.' . $count] = $this->renderMessage( + $exception, + $this->findTemplates($templates, $this->getId()) + ); + } + + return $messages; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/EmailException.php b/cacme/vendor/workerman/validation/library/Exceptions/EmailException.php new file mode 100644 index 0000000..ea2e4fd --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/EmailException.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions thrown by email rule. + * + * @author Alexandre Gomes Gaigalas + * @author Andrey Kolyshkin + * @author Eduardo Gulias Davis + * @author Henrique Moody + * @author Paul Karikari + */ +final class EmailException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的电子邮件', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是电子邮件', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/EndsWithException.php b/cacme/vendor/workerman/validation/library/Exceptions/EndsWithException.php new file mode 100644 index 0000000..8c446ef --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/EndsWithException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class EndsWithException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须以 {{endValue}} 结尾', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能以 {{endValue}} 结尾', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/EqualsException.php b/cacme/vendor/workerman/validation/library/Exceptions/EqualsException.php new file mode 100644 index 0000000..5c65c99 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/EqualsException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Ian Nisbet + */ +final class EqualsException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须等于 {{compareTo}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能等于 {{compareTo}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/EquivalentException.php b/cacme/vendor/workerman/validation/library/Exceptions/EquivalentException.php new file mode 100644 index 0000000..f2ebe0a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/EquivalentException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class EquivalentException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须与 {{compareTo}} 相等', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能与 {{compareTo}} 相等', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/EvenException.php b/cacme/vendor/workerman/validation/library/Exceptions/EvenException.php new file mode 100644 index 0000000..0c6be4c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/EvenException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions to be thrown by the Even Rule. + * + * @author Henrique Moody + * @author Jean Pimentel + * @author Paul Karikari + */ +final class EvenException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是偶数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是偶数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/Exception.php b/cacme/vendor/workerman/validation/library/Exceptions/Exception.php new file mode 100644 index 0000000..ce707ea --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/Exception.php @@ -0,0 +1,20 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use Throwable; + +/** + * @author Andy Wendt + * @author Henrique Moody + */ +interface Exception extends Throwable +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ExecutableException.php b/cacme/vendor/workerman/validation/library/Exceptions/ExecutableException.php new file mode 100644 index 0000000..45c5cd6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ExecutableException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author William Espindola + */ +final class ExecutableException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是可执行文件', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是可执行文件', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ExistsException.php b/cacme/vendor/workerman/validation/library/Exceptions/ExistsException.php new file mode 100644 index 0000000..6aff72a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ExistsException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author William Espindola + */ +final class ExistsException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须存在', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能存在', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ExtensionException.php b/cacme/vendor/workerman/validation/library/Exceptions/ExtensionException.php new file mode 100644 index 0000000..76133cf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ExtensionException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for Extension rule. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class ExtensionException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{extension}} 后缀', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{extension}} 后缀', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FactorException.php b/cacme/vendor/workerman/validation/library/Exceptions/FactorException.php new file mode 100644 index 0000000..94f1755 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FactorException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author David Meister + * @author Henrique Moody + */ +final class FactorException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{dividend}} 的因子', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{dividend}} 的因子', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FalseValException.php b/cacme/vendor/workerman/validation/library/Exceptions/FalseValException.php new file mode 100644 index 0000000..3e2bce6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FalseValException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class FalseValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不被视为 "False"', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 可视为 "False"', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FibonacciException.php b/cacme/vendor/workerman/validation/library/Exceptions/FibonacciException.php new file mode 100644 index 0000000..15ca8f0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FibonacciException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + * @author Samuel Heinzmann + */ +final class FibonacciException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的斐波纳契数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的斐波纳契数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FileException.php b/cacme/vendor/workerman/validation/library/Exceptions/FileException.php new file mode 100644 index 0000000..c5add8d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FileException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class FileException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是文件', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是文件', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FilterVarException.php b/cacme/vendor/workerman/validation/library/Exceptions/FilterVarException.php new file mode 100644 index 0000000..798b373 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FilterVarException.php @@ -0,0 +1,17 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class FilterVarException extends ValidationException +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FilteredValidationException.php b/cacme/vendor/workerman/validation/library/Exceptions/FilteredValidationException.php new file mode 100644 index 0000000..d81f5e9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FilteredValidationException.php @@ -0,0 +1,26 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +class FilteredValidationException extends ValidationException +{ + public const EXTRA = 'extra'; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + return $this->getParam('additionalChars') ? self::EXTRA : self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FiniteException.php b/cacme/vendor/workerman/validation/library/Exceptions/FiniteException.php new file mode 100644 index 0000000..6121146 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FiniteException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class FiniteException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有限数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有限数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FloatTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/FloatTypeException.php new file mode 100644 index 0000000..fa21625 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FloatTypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for FloatType rule. + * + * @author Henrique Moody + * @author Reginaldo Junior <76regi@gmail.com> + */ +final class FloatTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是float类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是float类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/FloatValException.php b/cacme/vendor/workerman/validation/library/Exceptions/FloatValException.php new file mode 100644 index 0000000..e8dd288 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/FloatValException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class FloatValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是浮点数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是浮点数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/GraphException.php b/cacme/vendor/workerman/validation/library/Exceptions/GraphException.php new file mode 100644 index 0000000..691cd14 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/GraphException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + */ +final class GraphException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含图形字符', + self::EXTRA => '{{name}} 只能包含图形字符和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含图形字符', + self::EXTRA => '{{name}} 不能包含图形字符或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/GreaterThanException.php b/cacme/vendor/workerman/validation/library/Exceptions/GreaterThanException.php new file mode 100644 index 0000000..cf2241a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/GreaterThanException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class GreaterThanException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须大于 {{compareTo}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能大于 {{compareTo}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/GroupedValidationException.php b/cacme/vendor/workerman/validation/library/Exceptions/GroupedValidationException.php new file mode 100644 index 0000000..555bbb4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/GroupedValidationException.php @@ -0,0 +1,47 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use function count; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +class GroupedValidationException extends NestedValidationException +{ + public const NONE = 'none'; + public const SOME = 'some'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::NONE => '所有必需的规则都必须传递给 {{name}}', + self::SOME => '这些规则必须传递给 {{name}}', + ], + self::MODE_NEGATIVE => [ + self::NONE => '所有规则都不能传递给 {{name}}', + self::SOME => '这些规则不能传递给 {{name}}', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + $numRules = $this->getParam('passed'); + $numFailed = count($this->getChildren()); + + return $numRules === $numFailed ? self::NONE : self::SOME; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/HexRgbColorException.php b/cacme/vendor/workerman/validation/library/Exceptions/HexRgbColorException.php new file mode 100644 index 0000000..4385e76 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/HexRgbColorException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Davide Pastore + * @author Henrique Moody + */ +final class HexRgbColorException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是十六进制RGB颜色', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是十六进制RGB颜色', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IbanException.php b/cacme/vendor/workerman/validation/library/Exceptions/IbanException.php new file mode 100644 index 0000000..854163a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IbanException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Mazen Touati + */ +final class IbanException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的IBAN', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的IBAN', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IdenticalException.php b/cacme/vendor/workerman/validation/library/Exceptions/IdenticalException.php new file mode 100644 index 0000000..cb81dfa --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IdenticalException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class IdenticalException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须与 {{compareTo}} 相同', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能与 {{compareTo}} 相同', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ImageException.php b/cacme/vendor/workerman/validation/library/Exceptions/ImageException.php new file mode 100644 index 0000000..f009df9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ImageException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Guilherme Siani + * @author Henrique Moody + */ +final class ImageException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的图像', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的图像', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ImeiException.php b/cacme/vendor/workerman/validation/library/Exceptions/ImeiException.php new file mode 100644 index 0000000..f310615 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ImeiException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Diego Oliveira + * @author Henrique Moody + */ +final class ImeiException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的IMEI', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的IMEI', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/InException.php b/cacme/vendor/workerman/validation/library/Exceptions/InException.php new file mode 100644 index 0000000..8baf958 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/InException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class InException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须在 {{haystack}} 中', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能在 {{haystack}} 中', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/InfiniteException.php b/cacme/vendor/workerman/validation/library/Exceptions/InfiniteException.php new file mode 100644 index 0000000..b02bd23 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/InfiniteException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + */ +final class InfiniteException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是无穷大的数字', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是无穷大的数字', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/InstanceException.php b/cacme/vendor/workerman/validation/library/Exceptions/InstanceException.php new file mode 100644 index 0000000..4a19a11 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/InstanceException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class InstanceException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{instanceName}} 的实例', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{instanceName}} 的实例', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IntTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/IntTypeException.php new file mode 100644 index 0000000..901f6a6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IntTypeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for IntType rule. + * + * @author Henrique Moody + */ +final class IntTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是integer类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是integer类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IntValException.php b/cacme/vendor/workerman/validation/library/Exceptions/IntValException.php new file mode 100644 index 0000000..c787c8b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IntValException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class IntValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是整数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是整数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/InvalidClassException.php b/cacme/vendor/workerman/validation/library/Exceptions/InvalidClassException.php new file mode 100644 index 0000000..72361fd --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/InvalidClassException.php @@ -0,0 +1,21 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception for invalid classes. + * + * @since 2.0.0 + * + * @author Henrique Moody + */ +final class InvalidClassException extends ComponentException +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IpException.php b/cacme/vendor/workerman/validation/library/Exceptions/IpException.php new file mode 100644 index 0000000..a0fe793 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IpException.php @@ -0,0 +1,47 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + * @author Luís Otávio Cobucci Oblonczyk + */ +final class IpException extends ValidationException +{ + public const NETWORK_RANGE = 'network_range'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是IP地址', + self::NETWORK_RANGE => '{{name}} 必须是 {{range}} 范围内的IP地址', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是IP地址', + self::NETWORK_RANGE => '{{name}} 不能是 {{range}} 范围内的IP地址', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if (!$this->getParam('range')) { + return self::STANDARD; + } + + return self::NETWORK_RANGE; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IsbnException.php b/cacme/vendor/workerman/validation/library/Exceptions/IsbnException.php new file mode 100644 index 0000000..657be01 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IsbnException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Moritz Fromm + */ +final class IsbnException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是ISBN', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是ISBN', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/IterableTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/IterableTypeException.php new file mode 100644 index 0000000..ce78933 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/IterableTypeException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class IterableTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是可迭代的', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是可迭代的', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/JsonException.php b/cacme/vendor/workerman/validation/library/Exceptions/JsonException.php new file mode 100644 index 0000000..6395550 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/JsonException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class JsonException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的JSON字符串', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的JSON字符串', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/KeyException.php b/cacme/vendor/workerman/validation/library/Exceptions/KeyException.php new file mode 100644 index 0000000..4f87fd6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/KeyException.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions to be thrown by the Attribute Rule. + * + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class KeyException extends NestedValidationException implements NonOmissibleException +{ + public const NOT_PRESENT = 'not_present'; + public const INVALID = 'invalid'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::NOT_PRESENT => '键 {{name}} 必须存在', + self::INVALID => '键 {{name}} 必须有效', + ], + self::MODE_NEGATIVE => [ + self::NOT_PRESENT => '键 {{name}} 不能存在', + self::INVALID => '键 {{name}} 必须无效', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + return $this->getParam('hasReference') ? self::INVALID : self::NOT_PRESENT; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/KeyNestedException.php b/cacme/vendor/workerman/validation/library/Exceptions/KeyNestedException.php new file mode 100644 index 0000000..9fc0a59 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/KeyNestedException.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions to be thrown by the Attribute Rule. + * + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Ivan Zinovyev + */ +final class KeyNestedException extends NestedValidationException implements NonOmissibleException +{ + public const NOT_PRESENT = 'not_present'; + public const INVALID = 'invalid'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::NOT_PRESENT => '找不到密钥链 {{name}} 的项', + self::INVALID => '密钥链 {{name}} 无效', + ], + self::MODE_NEGATIVE => [ + self::NOT_PRESENT => '密钥链 {{name}} 的项不存在', + self::INVALID => '密钥链 {{name}} 必须无效', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + return $this->getParam('hasReference') ? self::INVALID : self::NOT_PRESENT; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/KeySetException.php b/cacme/vendor/workerman/validation/library/Exceptions/KeySetException.php new file mode 100644 index 0000000..dc8fa0c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/KeySetException.php @@ -0,0 +1,50 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use function count; + +/** + * @author Henrique Moody + */ +final class KeySetException extends GroupedValidationException implements NonOmissibleException +{ + public const STRUCTURE = 'structure'; + public const STRUCTURE_EXTRA = 'structure_extra'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::NONE => '所有必需的规则都必须传递给 {{name}}', + self::SOME => '这些规则必须传递给 {{name}}', + self::STRUCTURE => '必须有键 {{keys}}', + + self::STRUCTURE_EXTRA => '不能有键 {{keys}}', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if (count($this->getParam('extraKeys'))) { + return self::STRUCTURE_EXTRA; + } + + if (count($this->getChildren()) === 0) { + return self::STRUCTURE; + } + + return parent::chooseTemplate(); + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/KeyValueException.php b/cacme/vendor/workerman/validation/library/Exceptions/KeyValueException.php new file mode 100644 index 0000000..473b4d6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/KeyValueException.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class KeyValueException extends ValidationException +{ + public const COMPONENT = 'component'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '键 {{name}} 必须存在', + self::COMPONENT => '{{baseKey}} 必须有效才能验证 {{comparedKey}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '键 {{name}} 不能存在', + self::COMPONENT => '{{baseKey}} 必须无效才能验证 {{comparedKey}}', + ], + ]; + + protected function chooseTemplate(): string + { + return $this->getParam('component') ? self::COMPONENT : self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LanguageCodeException.php b/cacme/vendor/workerman/validation/library/Exceptions/LanguageCodeException.php new file mode 100644 index 0000000..e066ca3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LanguageCodeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class LanguageCodeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的 ISO 639 {{set}} 语言编码', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的 ISO 639 {{set}} 语言编码', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LeapDateException.php b/cacme/vendor/workerman/validation/library/Exceptions/LeapDateException.php new file mode 100644 index 0000000..d05e976 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LeapDateException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + */ +final class LeapDateException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是闰日', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是闰日', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LeapYearException.php b/cacme/vendor/workerman/validation/library/Exceptions/LeapYearException.php new file mode 100644 index 0000000..a7b11c5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LeapYearException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class LeapYearException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是闰年', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是闰年', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LengthException.php b/cacme/vendor/workerman/validation/library/Exceptions/LengthException.php new file mode 100644 index 0000000..e106abe --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LengthException.php @@ -0,0 +1,70 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Henrique Moody + * @author Mazen Touati + */ +final class LengthException extends ValidationException +{ + public const BOTH = 'both'; + public const LOWER = 'lower'; + public const LOWER_INCLUSIVE = 'lower_inclusive'; + public const GREATER = 'greater'; + public const GREATER_INCLUSIVE = 'greater_inclusive'; + public const EXACT = 'exact'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::BOTH => '{{name}} 长度必须在 {{minValue}} 与 {{maxValue}} 之间', + self::LOWER => '{{name}} 长度必须大于 {{minValue}}', + self::LOWER_INCLUSIVE => '{{name}} 的长度必须大于或等于 {{minValue}}', + self::GREATER => '{{name}} 长度必须小于 {{maxValue}}', + self::GREATER_INCLUSIVE => '{{name}} 长度必须小于或等于 {{maxValue}}', + self::EXACT => '{{name}} 长度必须是 {{maxValue}}', + ], + self::MODE_NEGATIVE => [ + self::BOTH => '{{name}} 的长度不能介于 {{minValue}} 和 {{maxValue}} 之间', + self::LOWER => '{{name}} 长度不能大于 {{minValue}}', + self::LOWER_INCLUSIVE => '{{name}} 长度不能大于或等于 {{minValue}}', + self::GREATER => '{{name}} 长度不得小于 {{maxValue}}', + self::GREATER_INCLUSIVE => '{{name}} 长度不能小于或等于 {{maxValue}}', + self::EXACT => '{{name}} 长度不能是 {{maxValue}}', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + $isInclusive = $this->getParam('inclusive'); + + if (!$this->getParam('minValue')) { + return $isInclusive === true ? self::GREATER_INCLUSIVE : self::GREATER; + } + + if (!$this->getParam('maxValue')) { + return $isInclusive === true ? self::LOWER_INCLUSIVE : self::LOWER; + } + + if ($this->getParam('minValue') == $this->getParam('maxValue')) { + return self::EXACT; + } + + return self::BOTH; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LessThanException.php b/cacme/vendor/workerman/validation/library/Exceptions/LessThanException.php new file mode 100644 index 0000000..dce1920 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LessThanException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class LessThanException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须小于 {{compareTo}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能小于 {{compareTo}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LowercaseException.php b/cacme/vendor/workerman/validation/library/Exceptions/LowercaseException.php new file mode 100644 index 0000000..e715f0a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LowercaseException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class LowercaseException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是小写', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是小写', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/LuhnException.php b/cacme/vendor/workerman/validation/library/Exceptions/LuhnException.php new file mode 100644 index 0000000..e332cc5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/LuhnException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexander Gorshkov + * @author Danilo Correa + * @author Henrique Moody + */ +final class LuhnException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的Luhn编号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的Luhn编号', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MacAddressException.php b/cacme/vendor/workerman/validation/library/Exceptions/MacAddressException.php new file mode 100644 index 0000000..da4b0d9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MacAddressException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Fábio da Silva Ribeiro + * @author Henrique Moody + */ +final class MacAddressException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的MAC地址', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的MAC地址', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MaxAgeException.php b/cacme/vendor/workerman/validation/library/Exceptions/MaxAgeException.php new file mode 100644 index 0000000..c24bc0c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MaxAgeException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class MaxAgeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{age}} 年或者更少', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{age}} 年或者更少', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MaxException.php b/cacme/vendor/workerman/validation/library/Exceptions/MaxException.php new file mode 100644 index 0000000..a4976d3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MaxException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Andrew Peters + * @author Henrique Moody + */ +final class MaxException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须小于或等于 {{compareTo}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能小于或等于 {{compareTo}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MimetypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/MimetypeException.php new file mode 100644 index 0000000..5a37c26 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MimetypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for Mimetype rule. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class MimetypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须具有 {{mimetype}} MIME类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能有 {{mimetype}} MIME类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MinAgeException.php b/cacme/vendor/workerman/validation/library/Exceptions/MinAgeException.php new file mode 100644 index 0000000..489e339 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MinAgeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Jean Pimentel + */ +final class MinAgeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{age}} 必须是年或以上', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{age}} 年或更长', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MinException.php b/cacme/vendor/workerman/validation/library/Exceptions/MinException.php new file mode 100644 index 0000000..72c4779 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MinException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class MinException extends ValidationException +{ + public const INCLUSIVE = 'inclusive'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须大于或等于 {{compareTo}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能大于或等于 {{compareTo}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/MultipleException.php b/cacme/vendor/workerman/validation/library/Exceptions/MultipleException.php new file mode 100644 index 0000000..fbd27f8 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/MultipleException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class MultipleException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{multipleOf}} 的倍数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{multipleOf}} 的倍数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NegativeException.php b/cacme/vendor/workerman/validation/library/Exceptions/NegativeException.php new file mode 100644 index 0000000..840d4ba --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NegativeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Ismael Elias + */ +final class NegativeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须为负数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能为负数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NestedValidationException.php b/cacme/vendor/workerman/validation/library/Exceptions/NestedValidationException.php new file mode 100644 index 0000000..460afe9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NestedValidationException.php @@ -0,0 +1,255 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use IteratorAggregate; +use RecursiveIteratorIterator; +use SplObjectStorage; + +use function array_shift; +use function count; +use function current; +use function implode; +use function is_array; +use function spl_object_hash; +use function sprintf; +use function str_repeat; + +use const PHP_EOL; + +/** + * Exception for nested validations. + * + * This exception allows to have exceptions inside itself and providers methods + * to handle them and to retrieve nested messages based on itself and its + * children. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Jonathan Stewmon + * @author Wojciech Frącz + */ +class NestedValidationException extends ValidationException implements IteratorAggregate +{ + /** + * @var ValidationException[] + */ + private $exceptions = []; + + /** + * Returns the exceptions that are children of the exception. + * + * @return ValidationException[] + */ + public function getChildren(): array + { + return $this->exceptions; + } + + /** + * Adds a child to the exception. + */ + public function addChild(ValidationException $exception): self + { + $this->exceptions[spl_object_hash($exception)] = $exception; + + return $this; + } + + /** + * Adds children to the exception. + * + * @param ValidationException[] $exceptions + */ + public function addChildren(array $exceptions): self + { + foreach ($exceptions as $exception) { + $this->addChild($exception); + } + + return $this; + } + + /** + * @return SplObjectStorage + */ + public function getIterator(): SplObjectStorage + { + /** @var SplObjectStorage */ + $childrenExceptions = new SplObjectStorage(); + $recursiveIteratorIterator = $this->getRecursiveIterator(); + + $lastDepth = 0; + $lastDepthOriginal = 0; + $knownDepths = []; + foreach ($recursiveIteratorIterator as $childException) { + if ($this->isOmissible($childException)) { + continue; + } + + $currentDepth = $lastDepth; + $currentDepthOriginal = $recursiveIteratorIterator->getDepth() + 1; + + if (isset($knownDepths[$currentDepthOriginal])) { + $currentDepth = $knownDepths[$currentDepthOriginal]; + } elseif ($currentDepthOriginal > $lastDepthOriginal) { + ++$currentDepth; + } + + if (!isset($knownDepths[$currentDepthOriginal])) { + $knownDepths[$currentDepthOriginal] = $currentDepth; + } + + $lastDepth = $currentDepth; + $lastDepthOriginal = $currentDepthOriginal; + + $childrenExceptions->attach($childException, $currentDepth); + } + + return $childrenExceptions; + } + + /** + * Returns a key->value array with all the messages of the exception. + * + * In this array the "keys" are the ids of the exceptions (defined name or + * name of the rule) and the values are the message. + * + * Once templates are passed it overwrites the templates of the given + * messages. + * + * @param string[]|string[][] $templates + * + * @return string[] + */ + public function getMessages(array $templates = []): array + { + $messages = [$this->getId() => $this->renderMessage($this, $templates)]; + foreach ($this->getChildren() as $exception) { + $id = $exception->getId(); + if (!$exception instanceof self) { + $messages[$id] = $this->renderMessage( + $exception, + $this->findTemplates($templates, $this->getId()) + ); + continue; + } + + $messages[$id] = $exception->getMessages($this->findTemplates($templates, $id, $this->getId())); + if (count($messages[$id]) > 1) { + continue; + } + + $messages[$id] = current($messages[$exception->getId()]); + } + + if (count($messages) > 1) { + unset($messages[$this->getId()]); + } + + return $messages; + } + + /** + * Returns a string with all the messages of the exception. + */ + public function getFullMessage(): string + { + $messages = []; + $leveler = 1; + + if (!$this->isOmissible($this)) { + $leveler = 0; + $messages[] = sprintf('- %s', $this->getMessage()); + } + + $exceptions = $this->getIterator(); + /** @var ValidationException $exception */ + foreach ($exceptions as $exception) { + $messages[] = sprintf( + '%s- %s', + str_repeat(' ', (int) ($exceptions[$exception] - $leveler) * 2), + $exception->getMessage() + ); + } + + return implode(PHP_EOL, $messages); + } + + /** + * @param string[] $templates + */ + protected function renderMessage(ValidationException $exception, array $templates): string + { + if (isset($templates[$exception->getId()])) { + $exception->updateTemplate($templates[$exception->getId()]); + } + + return $exception->getMessage(); + } + + /** + * @param string[] $templates + * @param mixed ...$ids + * + * @return string[] + */ + protected function findTemplates(array $templates, ...$ids): array + { + while (count($ids) > 0) { + $id = array_shift($ids); + if (!isset($templates[$id])) { + continue; + } + + if (!is_array($templates[$id])) { + continue; + } + + $templates = $templates[$id]; + } + + return $templates; + } + + /** + * @return RecursiveIteratorIterator + */ + private function getRecursiveIterator(): RecursiveIteratorIterator + { + return new RecursiveIteratorIterator( + new RecursiveExceptionIterator($this), + RecursiveIteratorIterator::SELF_FIRST + ); + } + + private function isOmissible(Exception $exception): bool + { + if (!$exception instanceof self) { + return false; + } + + if (count($exception->getChildren()) !== 1) { + return false; + } + + /** @var ValidationException $childException */ + $childException = current($exception->getChildren()); + if ($childException->getMessage() === $exception->getMessage()) { + return true; + } + + if ($exception->hasCustomTemplate()) { + return $childException->hasCustomTemplate(); + } + + return !$childException instanceof NonOmissibleException; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NfeAccessKeyException.php b/cacme/vendor/workerman/validation/library/Exceptions/NfeAccessKeyException.php new file mode 100644 index 0000000..ec6809e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NfeAccessKeyException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andrey Knupp Vital + * @author Danilo Correa + * @author Henrique Moody + */ +final class NfeAccessKeyException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的NFe访问密钥', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的NFe访问密钥', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NifException.php b/cacme/vendor/workerman/validation/library/Exceptions/NifException.php new file mode 100644 index 0000000..7169fe2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NifException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Julián Gutiérrez + */ +final class NifException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是NIF', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是NIF', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NipException.php b/cacme/vendor/workerman/validation/library/Exceptions/NipException.php new file mode 100644 index 0000000..a444815 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NipException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Tomasz Regdos + */ +final class NipException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的波兰增值税标识号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的波兰增值税标识号', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NoException.php b/cacme/vendor/workerman/validation/library/Exceptions/NoException.php new file mode 100644 index 0000000..5831c18 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NoException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class NoException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不被视为 "否"', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 被认为是 "否"', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NoWhitespaceException.php b/cacme/vendor/workerman/validation/library/Exceptions/NoWhitespaceException.php new file mode 100644 index 0000000..dcc9cef --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NoWhitespaceException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class NoWhitespaceException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不能包含空格', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 必须包含空格', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NonOmissibleException.php b/cacme/vendor/workerman/validation/library/Exceptions/NonOmissibleException.php new file mode 100644 index 0000000..adb95f4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NonOmissibleException.php @@ -0,0 +1,18 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andy Wendt + * @author Henrique Moody + */ +interface NonOmissibleException extends Exception +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NoneOfException.php b/cacme/vendor/workerman/validation/library/Exceptions/NoneOfException.php new file mode 100644 index 0000000..f737b42 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NoneOfException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class NoneOfException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '这些规则都不能传递给 {{name}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '所有这些规则都必须传递给 {{name}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NotBlankException.php b/cacme/vendor/workerman/validation/library/Exceptions/NotBlankException.php new file mode 100644 index 0000000..27230da --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NotBlankException.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class NotBlankException extends ValidationException +{ + public const NAMED = 'named'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '值不能为空', + self::NAMED => '{{name}} 不能为空', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '值必须为空', + self::NAMED => '{{name}} 必须为空', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('input') || $this->getParam('name')) { + return self::NAMED; + } + + return self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NotEmojiException.php b/cacme/vendor/workerman/validation/library/Exceptions/NotEmojiException.php new file mode 100644 index 0000000..43f3237 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NotEmojiException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Mazen Touati + */ +final class NotEmojiException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不能包含表情符号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 必须包含表情符号', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NotEmptyException.php b/cacme/vendor/workerman/validation/library/Exceptions/NotEmptyException.php new file mode 100644 index 0000000..cbff8f5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NotEmptyException.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Bram Van der Sype + * @author Henrique Moody + */ +final class NotEmptyException extends ValidationException +{ + public const NAMED = 'named'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '值不能为空', + self::NAMED => '{{name}} 不能为空', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '值必须为空', + self::NAMED => '{{name}} 必须为空', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('input') || $this->getParam('name')) { + return self::NAMED; + } + + return self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NotException.php b/cacme/vendor/workerman/validation/library/Exceptions/NotException.php new file mode 100644 index 0000000..9763d87 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NotException.php @@ -0,0 +1,18 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class NotException extends GroupedValidationException +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NotOptionalException.php b/cacme/vendor/workerman/validation/library/Exceptions/NotOptionalException.php new file mode 100644 index 0000000..ab2321f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NotOptionalException.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class NotOptionalException extends ValidationException +{ + public const NAMED = 'named'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '该值不能是可选的', + self::NAMED => '{{name}} 不能是可选的', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '该值必须是可选的', + self::NAMED => '{{name}} 必须是可选的', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('input') || $this->getParam('name')) { + return self::NAMED; + } + + return self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NullTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/NullTypeException.php new file mode 100644 index 0000000..53641e7 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NullTypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for NullType. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class NullTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须为 null', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能为 null', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NullableException.php b/cacme/vendor/workerman/validation/library/Exceptions/NullableException.php new file mode 100644 index 0000000..803e7b9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NullableException.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Jens Segers + */ +final class NullableException extends ValidationException +{ + public const NAMED = 'named'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '值必须为nullable', + self::NAMED => '{{name}} 必须为nullable', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '值不能为null', + self::NAMED => '{{name}} 不能为null', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('input') || $this->getParam('name')) { + return self::NAMED; + } + + return self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NumberException.php b/cacme/vendor/workerman/validation/library/Exceptions/NumberException.php new file mode 100644 index 0000000..c52ff86 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NumberException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Ismael Elias + * @author Vitaliy + */ +final class NumberException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是数字', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能为数字', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/NumericValException.php b/cacme/vendor/workerman/validation/library/Exceptions/NumericValException.php new file mode 100644 index 0000000..89148af --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/NumericValException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Henrique Moody + */ +final class NumericValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是数字', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是数字', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ObjectTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/ObjectTypeException.php new file mode 100644 index 0000000..a3431ab --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ObjectTypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for ObjectType rule. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class ObjectTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是object类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是object类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/OddException.php b/cacme/vendor/workerman/validation/library/Exceptions/OddException.php new file mode 100644 index 0000000..60ab77a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/OddException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class OddException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是奇数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是奇数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/OneOfException.php b/cacme/vendor/workerman/validation/library/Exceptions/OneOfException.php new file mode 100644 index 0000000..059ae83 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/OneOfException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Bradyn Poulsen + * @author Henrique Moody + */ +final class OneOfException extends NestedValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '这些规则中只有一个必须传递给 {{name}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '这些规则中只有一个不能传递给 {{name}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/OptionalException.php b/cacme/vendor/workerman/validation/library/Exceptions/OptionalException.php new file mode 100644 index 0000000..2ca4333 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/OptionalException.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class OptionalException extends ValidationException +{ + public const NAMED = 'named'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '该值必须是可选的', + self::NAMED => '{{name}} 必须是可选的', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '该值不能是可选的', + self::NAMED => '{{name}} 不能是可选的', + ], + ]; + + protected function chooseTemplate(): string + { + return $this->getParam('name') ? self::NAMED : self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PerfectSquareException.php b/cacme/vendor/workerman/validation/library/Exceptions/PerfectSquareException.php new file mode 100644 index 0000000..c01888a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PerfectSquareException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + * @author Kleber Hamada Sato + */ +final class PerfectSquareException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的完全正方形', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的完全正方形', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PeselException.php b/cacme/vendor/workerman/validation/library/Exceptions/PeselException.php new file mode 100644 index 0000000..4abe05a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PeselException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + * @author Tomasz Regdos + */ +final class PeselException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的比索', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的比索', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PhoneException.php b/cacme/vendor/workerman/validation/library/Exceptions/PhoneException.php new file mode 100644 index 0000000..3d2fd61 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PhoneException.php @@ -0,0 +1,55 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use Respect\Validation\Helpers\CountryInfo; + +/** + * @author Danilo Correa + * @author Henrique Moody + * @author Michael Firsikov + */ +final class PhoneException extends ValidationException +{ + public const FOR_COUNTRY = 'for_country'; + public const INTERNATIONAL = 'international'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::INTERNATIONAL => '{{name}} 必须是有效的电话号码', + self::FOR_COUNTRY => '{{name}} 必须是 {{countryName}} 的有效电话号码', + ], + self::MODE_NEGATIVE => [ + self::INTERNATIONAL => '{{name}} 不能是有效的电话号码', + self::FOR_COUNTRY => '{{name}} 必须是 {{countryName}} 的有效电话号码', + + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + $countryCode = $this->getParam('countryCode'); + + if (!$countryCode) { + return self::INTERNATIONAL; + } + + $countryInfo = new CountryInfo($countryCode); + $this->setParam('countryName', $countryInfo->getCountry()); + + return self::FOR_COUNTRY; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PhpLabelException.php b/cacme/vendor/workerman/validation/library/Exceptions/PhpLabelException.php new file mode 100644 index 0000000..1b710bc --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PhpLabelException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class PhpLabelException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的PHP标签', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的PHP标签', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PisException.php b/cacme/vendor/workerman/validation/library/Exceptions/PisException.php new file mode 100644 index 0000000..cd6f70f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PisException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Bruno Koga + * @author Danilo Correa + * @author Henrique Moody + */ +final class PisException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的PIS编号', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的PIS编号', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PolishIdCardException.php b/cacme/vendor/workerman/validation/library/Exceptions/PolishIdCardException.php new file mode 100644 index 0000000..1143754 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PolishIdCardException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class PolishIdCardException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的波兰身份证号码', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的波兰身份证号码r', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PortugueseNifException.php b/cacme/vendor/workerman/validation/library/Exceptions/PortugueseNifException.php new file mode 100644 index 0000000..d3b991d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PortugueseNifException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Gonçalo Andrade + */ +final class PortugueseNifException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} must be a Portuguese NIF', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} must not be a Portuguese NIF', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PositiveException.php b/cacme/vendor/workerman/validation/library/Exceptions/PositiveException.php new file mode 100644 index 0000000..34d030c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PositiveException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Ismael Elias + */ +final class PositiveException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须为正', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能为正', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PostalCodeException.php b/cacme/vendor/workerman/validation/library/Exceptions/PostalCodeException.php new file mode 100644 index 0000000..9e69532 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PostalCodeException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class PostalCodeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{countryCode}} 上的有效邮政编码', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{countryCode}} 上的有效邮政编码', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PrimeNumberException.php b/cacme/vendor/workerman/validation/library/Exceptions/PrimeNumberException.php new file mode 100644 index 0000000..f9358ab --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PrimeNumberException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Ismael Elias + * @author Kleber Hamada Sato + */ +final class PrimeNumberException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的质数', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的质数', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PrintableException.php b/cacme/vendor/workerman/validation/library/Exceptions/PrintableException.php new file mode 100644 index 0000000..f6c50e4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PrintableException.php @@ -0,0 +1,35 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions to be thrown by the Printable Rule. + * + * @author Alexandre Gomes Gaigalas + * @author Andre Ramaciotti + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class PrintableException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含可打印字符', + self::EXTRA => '{{name}} 只能包含可打印字符和 "{{additionalChars}}"', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含可打印字符', + self::EXTRA => '{{name}} 不能包含可打印字符或 "{{additionalChars}}"', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PublicDomainSuffixException.php b/cacme/vendor/workerman/validation/library/Exceptions/PublicDomainSuffixException.php new file mode 100644 index 0000000..69e65cf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PublicDomainSuffixException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +class PublicDomainSuffixException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} must be a public domain suffix', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} must be a public domain suffix', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/PunctException.php b/cacme/vendor/workerman/validation/library/Exceptions/PunctException.php new file mode 100644 index 0000000..6e251c9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/PunctException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + */ +final class PunctException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含标点符号', + self::EXTRA => '{{name}} 只能包含标点符号和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含标点符号', + self::EXTRA => '{{name}} 不能包含标点符号或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ReadableException.php b/cacme/vendor/workerman/validation/library/Exceptions/ReadableException.php new file mode 100644 index 0000000..85ef1cb --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ReadableException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class ReadableException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须可读', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能可读', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/RecursiveExceptionIterator.php b/cacme/vendor/workerman/validation/library/Exceptions/RecursiveExceptionIterator.php new file mode 100644 index 0000000..a95ef72 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/RecursiveExceptionIterator.php @@ -0,0 +1,85 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use ArrayIterator; +use Countable; +use RecursiveIterator; +use UnexpectedValueException; + +/** + * @author Henrique Moody + * + * @implements RecursiveIterator + */ +final class RecursiveExceptionIterator implements RecursiveIterator, Countable +{ + /** + * @var ArrayIterator|ValidationException[] + */ + private $exceptions; + + public function __construct(NestedValidationException $parent) + { + $this->exceptions = new ArrayIterator($parent->getChildren()); + } + + public function count(): int + { + return $this->exceptions->count(); + } + + public function hasChildren(): bool + { + if (!$this->valid()) { + return false; + } + + return $this->current() instanceof NestedValidationException; + } + + public function getChildren(): self + { + $exception = $this->current(); + if (!$exception instanceof NestedValidationException) { + throw new UnexpectedValueException(); + } + + return new static($exception); + } + + /** + * @return ValidationException|NestedValidationException + */ + public function current(): ValidationException + { + return $this->exceptions->current(); + } + + public function key(): int + { + return $this->exceptions->key(); + } + + public function next(): void + { + $this->exceptions->next(); + } + + public function rewind(): void + { + $this->exceptions->rewind(); + } + + public function valid(): bool + { + return $this->exceptions->valid(); + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/RegexException.php b/cacme/vendor/workerman/validation/library/Exceptions/RegexException.php new file mode 100644 index 0000000..c6f4e28 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/RegexException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Henrique Moody + */ +final class RegexException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 对照 {{regex}} 进行验证', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能针对 {{regex}} 进行验证', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ResourceTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/ResourceTypeException.php new file mode 100644 index 0000000..bbbeda6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ResourceTypeException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for ResourceType. + * + * @author Henrique Moody + */ +final class ResourceTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是资源', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是资源', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/RomanException.php b/cacme/vendor/workerman/validation/library/Exceptions/RomanException.php new file mode 100644 index 0000000..227d4eb --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/RomanException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Jean Pimentel + */ +final class RomanException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的罗马数字', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的罗马数字', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ScalarValException.php b/cacme/vendor/workerman/validation/library/Exceptions/ScalarValException.php new file mode 100644 index 0000000..622b60d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ScalarValException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class ScalarValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是标量值', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是标量值', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SfException.php b/cacme/vendor/workerman/validation/library/Exceptions/SfException.php new file mode 100644 index 0000000..d512265 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SfException.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class SfException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须对 {{constraint}} 有效', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能对 {{constraint}} 有效', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SizeException.php b/cacme/vendor/workerman/validation/library/Exceptions/SizeException.php new file mode 100644 index 0000000..5f441ff --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SizeException.php @@ -0,0 +1,54 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exception class for Size rule. + * + * @author Henrique Moody + */ +final class SizeException extends NestedValidationException +{ + public const BOTH = 'both'; + public const LOWER = 'lower'; + public const GREATER = 'greater'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::BOTH => '{{name}} 必须介于 {{minSize}} 和 {{maxSize}} 之间', + self::LOWER => '{{name}} 必须大于 {{minSize}}', + self::GREATER => '{{name}} 必须小于 {{maxSize}}', + ], + self::MODE_NEGATIVE => [ + self::BOTH => '{{name}} 不能介于 {{minSize}} 和 {{maxSize}} 之间', + self::LOWER => '{{name}} 不能大于 {{minSize}}', + self::GREATER => '{{name}} 不能小于 {{maxSize}}', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if (!$this->getParam('minValue')) { + return self::GREATER; + } + + if (!$this->getParam('maxValue')) { + return self::LOWER; + } + + return self::BOTH; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SlugException.php b/cacme/vendor/workerman/validation/library/Exceptions/SlugException.php new file mode 100644 index 0000000..8b9263a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SlugException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Carlos André Ferrari + * @author Danilo Correa + * @author Henrique Moody + */ +final class SlugException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的 slug', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的 slug', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SortedException.php b/cacme/vendor/workerman/validation/library/Exceptions/SortedException.php new file mode 100644 index 0000000..16a00a0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SortedException.php @@ -0,0 +1,44 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use Respect\Validation\Rules\Sorted; + +/** + * @author Henrique Moody + * @author Mikhail Vyrtsev + */ +final class SortedException extends ValidationException +{ + public const ASCENDING = 'ascending'; + public const DESCENDING = 'descending'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::ASCENDING => '{{name}} 必须按升序排序', + self::DESCENDING => '{{name}} 必须按降序排序', + ], + self::MODE_NEGATIVE => [ + self::ASCENDING => '{{name}} 不能按升序排序', + self::DESCENDING => '{{name}} 不能按降序排序', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + return $this->getParam('direction') === Sorted::ASCENDING ? self::ASCENDING : self::DESCENDING; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SpaceException.php b/cacme/vendor/workerman/validation/library/Exceptions/SpaceException.php new file mode 100644 index 0000000..b893445 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SpaceException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andre Ramaciotti + * @author Henrique Moody + */ +final class SpaceException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含空格字符', + self::EXTRA => '{{name}} 只能包含空格字符和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含空格字符', + self::EXTRA => '{{name}} 不能包含空格字符或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/StartsWithException.php b/cacme/vendor/workerman/validation/library/Exceptions/StartsWithException.php new file mode 100644 index 0000000..2c3adaf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/StartsWithException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class StartsWithException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须以 {{startValue}} 开头', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能以 {{startValue}} 开头', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/StringTypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/StringTypeException.php new file mode 100644 index 0000000..bf8ac4e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/StringTypeException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class StringTypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是string类型', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是string类型', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/StringValException.php b/cacme/vendor/workerman/validation/library/Exceptions/StringValException.php new file mode 100644 index 0000000..beca523 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/StringValException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class StringValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是字符串', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是字符串', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SubdivisionCodeException.php b/cacme/vendor/workerman/validation/library/Exceptions/SubdivisionCodeException.php new file mode 100644 index 0000000..3d193b1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SubdivisionCodeException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +class SubdivisionCodeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{countryName}} 的细分代码', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{countryName}} 的细分代码', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SubsetException.php b/cacme/vendor/workerman/validation/library/Exceptions/SubsetException.php new file mode 100644 index 0000000..c6a2dba --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SubsetException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Singwai Chan + */ +final class SubsetException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{superset}} 的子集', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{superset}} 的子集', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/SymbolicLinkException.php b/cacme/vendor/workerman/validation/library/Exceptions/SymbolicLinkException.php new file mode 100644 index 0000000..5c33f02 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/SymbolicLinkException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Gus Antoniassi + * @author Henrique Moody + */ +final class SymbolicLinkException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是符号链接', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是符号链接', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/TimeException.php b/cacme/vendor/workerman/validation/library/Exceptions/TimeException.php new file mode 100644 index 0000000..27c9b2a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/TimeException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class TimeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是格式为 {{sample}} 的有效时间', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是格式为 {{sample}} 的有效时间', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/TldException.php b/cacme/vendor/workerman/validation/library/Exceptions/TldException.php new file mode 100644 index 0000000..439ee95 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/TldException.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions thrown by Tld Rule. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Nick Lombard + * @author Paul Karikari + */ +final class TldException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的顶级域名', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的顶级域名', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/TrueValException.php b/cacme/vendor/workerman/validation/library/Exceptions/TrueValException.php new file mode 100644 index 0000000..8f676a7 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/TrueValException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions thrown by TrueVal rule. + * + * @author Henrique Moody + * @author Paul Karikari + */ +final class TrueValException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不被视为 "True"', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 被视为 "True"', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/TypeException.php b/cacme/vendor/workerman/validation/library/Exceptions/TypeException.php new file mode 100644 index 0000000..e61462f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/TypeException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions thrown by Type rule. + * + * @author Henrique Moody + * @author Paul Karikari + */ +final class TypeException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是 {{type}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是 {{type}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/UniqueException.php b/cacme/vendor/workerman/validation/library/Exceptions/UniqueException.php new file mode 100644 index 0000000..fa4f41d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/UniqueException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions thrown by Unique rule. + * + * @author Henrique Moody + * @author Krzysztof Śmiałek + * @author Paul Karikari + */ +final class UniqueException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不能包含重复项', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 必须包含重复项', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/UploadedException.php b/cacme/vendor/workerman/validation/library/Exceptions/UploadedException.php new file mode 100644 index 0000000..b29d6c2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/UploadedException.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * Exceptions thrown by Uploaded rule. + * + * @author Fajar Khairil + * @author Henrique Moody + * @author Paul Karikari + */ +final class UploadedException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是上传的文件', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是上传的文件', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/UppercaseException.php b/cacme/vendor/workerman/validation/library/Exceptions/UppercaseException.php new file mode 100644 index 0000000..c715a2f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/UppercaseException.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class UppercaseException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须大写', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能大写', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/UrlException.php b/cacme/vendor/workerman/validation/library/Exceptions/UrlException.php new file mode 100644 index 0000000..b0f5b19 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/UrlException.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class UrlException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是URL', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是URL', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/UuidException.php b/cacme/vendor/workerman/validation/library/Exceptions/UuidException.php new file mode 100644 index 0000000..a893d9b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/UuidException.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Dick van der Heiden + * @author Henrique Moody + * @author Michael Weimann + */ +final class UuidException extends ValidationException +{ + public const VERSION = 'version'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的UUID', + self::VERSION => '{{name}} 必须是有效的UUID版本 {{version}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的UUID', + self::VERSION => '{{name}} 不能是有效的UUID版本 {{version}}', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('version')) { + return self::VERSION; + } + + return self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ValidationException.php b/cacme/vendor/workerman/validation/library/Exceptions/ValidationException.php new file mode 100644 index 0000000..878ec3d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ValidationException.php @@ -0,0 +1,158 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +use InvalidArgumentException; +use Respect\Validation\Message\Formatter; + +use function key; + +/** + * Default exception class for rule validations. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +class ValidationException extends InvalidArgumentException implements Exception +{ + public const MODE_DEFAULT = 'default'; + public const MODE_NEGATIVE = 'negative'; + public const STANDARD = 'standard'; + + /** + * Contains the default templates for exception message. + * + * @var string[][] + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须有效', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能有效', + ], + ]; + + /** + * @var mixed + */ + private $input; + + /** + * @var string + */ + private $id; + + /** + * @var string + */ + private $mode = self::MODE_DEFAULT; + + /** + * @var mixed[] + */ + private $params = []; + + /** + * @var Formatter + */ + private $formatter; + + /** + * @var string + */ + private $template; + + /** + * @param mixed $input + * @param mixed[] $params + */ + public function __construct($input, string $id, array $params, Formatter $formatter) + { + $this->input = $input; + $this->id = $id; + $this->params = $params; + $this->formatter = $formatter; + $this->template = $this->chooseTemplate(); + + parent::__construct($this->createMessage()); + } + + public function getId(): string + { + return $this->id; + } + + /** + * @return mixed[] + */ + public function getParams(): array + { + return $this->params; + } + + /** + * @return mixed|null + */ + public function getParam(string $name) + { + return $this->params[$name] ?? null; + } + + public function setParam(string $name, mixed $value): void + { + $this->params[$name] = $value; + } + + public function updateMode(string $mode): void + { + $this->mode = $mode; + $this->message = $this->createMessage(); + } + + public function updateTemplate(string $template): void + { + $this->template = $template; + $this->message = $this->createMessage(); + } + + /** + * @param mixed[] $params + */ + public function updateParams(array $params): void + { + $this->params = $params; + $this->message = $this->createMessage(); + } + + public function hasCustomTemplate(): bool + { + return isset($this->defaultTemplates[$this->mode][$this->template]) === false; + } + + protected function chooseTemplate(): string + { + return (string) key($this->defaultTemplates[$this->mode]); + } + + private function createMessage(): string + { + return $this->formatter->format( + $this->defaultTemplates[$this->mode][$this->template] ?? $this->template, + $this->input, + $this->params + ); + } + + public function __toString(): string + { + return $this->getMessage(); + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/ValidatorException.php b/cacme/vendor/workerman/validation/library/Exceptions/ValidatorException.php new file mode 100644 index 0000000..7a27c39 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/ValidatorException.php @@ -0,0 +1,17 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + */ +final class ValidatorException extends AllOfException +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/VersionException.php b/cacme/vendor/workerman/validation/library/Exceptions/VersionException.php new file mode 100644 index 0000000..954687c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/VersionException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class VersionException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是版本', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是版本', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/VideoUrlException.php b/cacme/vendor/workerman/validation/library/Exceptions/VideoUrlException.php new file mode 100644 index 0000000..7135224 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/VideoUrlException.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + * @author Ricardo Gobbo + */ +final class VideoUrlException extends ValidationException +{ + public const SERVICE = 'service'; + + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是有效的视频URL', + self::SERVICE => '{{name}} 必须是有效的 {{service}} 视频URL', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是有效的视频URL', + self::SERVICE => '{{name}} 不能是有效的 {{service}} 视频URL', + ], + ]; + + /** + * {@inheritDoc} + */ + protected function chooseTemplate(): string + { + if ($this->getParam('service')) { + return self::SERVICE; + } + + return self::STANDARD; + } +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/VowelException.php b/cacme/vendor/workerman/validation/library/Exceptions/VowelException.php new file mode 100644 index 0000000..45186a3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/VowelException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Henrique Moody + * @author Kleber Hamada Sato + */ +final class VowelException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含元音', + self::EXTRA => '{{name}} 只能包含元音和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含元音', + self::EXTRA => '{{name}} 不能包含元音或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/WhenException.php b/cacme/vendor/workerman/validation/library/Exceptions/WhenException.php new file mode 100644 index 0000000..76d1812 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/WhenException.php @@ -0,0 +1,19 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Antonio Spinelli + * @author Danilo Correa + * @author Henrique Moody + */ +final class WhenException extends ValidationException +{ +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/WritableException.php b/cacme/vendor/workerman/validation/library/Exceptions/WritableException.php new file mode 100644 index 0000000..1680490 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/WritableException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Danilo Correa + * @author Henrique Moody + */ +final class WritableException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 必须是可写的', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能是可写的', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/XdigitException.php b/cacme/vendor/workerman/validation/library/Exceptions/XdigitException.php new file mode 100644 index 0000000..f0142c8 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/XdigitException.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Andre Ramaciotti + * @author Henrique Moody + */ +final class XdigitException extends FilteredValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 只能包含十六进制数字', + self::EXTRA => '{{name}} 只能包含十六进制数字和 {{additionalChars}}', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 不能包含十六进制数字', + self::EXTRA => '{{name}} 不能包含十六进制数字或 {{additionalChars}}', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Exceptions/YesException.php b/cacme/vendor/workerman/validation/library/Exceptions/YesException.php new file mode 100644 index 0000000..ede9b1a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Exceptions/YesException.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Exceptions; + +/** + * @author Cameron Hall + * @author Henrique Moody + */ +final class YesException extends ValidationException +{ + /** + * {@inheritDoc} + */ + protected $defaultTemplates = [ + self::MODE_DEFAULT => [ + self::STANDARD => '{{name}} 不被认为是 "Yes"', + ], + self::MODE_NEGATIVE => [ + self::STANDARD => '{{name}} 被认为是 "Yes"', + ], + ]; +} diff --git a/cacme/vendor/workerman/validation/library/Factory.php b/cacme/vendor/workerman/validation/library/Factory.php new file mode 100644 index 0000000..5260556 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Factory.php @@ -0,0 +1,266 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation; + +use ReflectionClass; +use ReflectionException; +use ReflectionObject; +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Exceptions\InvalidClassException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Message\Formatter; +use Respect\Validation\Message\ParameterStringifier; +use Respect\Validation\Message\Stringifier\KeepOriginalStringName; + +use function array_merge; +use function lcfirst; +use function sprintf; +use function str_replace; +use function trim; +use function ucfirst; + +/** + * Factory of objects. + * + * @author Augusto Pascutti + * @author Henrique Moody + */ +final class Factory +{ + /** + * @var string[] + */ + private $rulesNamespaces = ['Respect\\Validation\\Rules']; + + /** + * @var string[] + */ + private $exceptionsNamespaces = ['Respect\\Validation\\Exceptions']; + + /** + * @var callable + */ + private $translator = 'strval'; + + /** + * @var ParameterStringifier + */ + private $parameterStringifier; + + /** + * Default instance of the Factory. + * + * @var Factory + */ + private static $defaultInstance; + + public function __construct() + { + $this->parameterStringifier = new KeepOriginalStringName(); + } + + /** + * Returns the default instance of the Factory. + */ + public static function getDefaultInstance(): self + { + if (self::$defaultInstance === null) { + self::$defaultInstance = new self(); + } + + return self::$defaultInstance; + } + + public function withRuleNamespace(string $rulesNamespace): self + { + $clone = clone $this; + $clone->rulesNamespaces[] = trim($rulesNamespace, '\\'); + + return $clone; + } + + public function withExceptionNamespace(string $exceptionsNamespace): self + { + $clone = clone $this; + $clone->exceptionsNamespaces[] = trim($exceptionsNamespace, '\\'); + + return $clone; + } + + public function withTranslator(callable $translator): self + { + $clone = clone $this; + $clone->translator = $translator; + + return $clone; + } + + public function withParameterStringifier(ParameterStringifier $parameterStringifier): self + { + $clone = clone $this; + $clone->parameterStringifier = $parameterStringifier; + + return $clone; + } + + /** + * Creates a rule. + * + * @param mixed[] $arguments + * + * @throws ComponentException + */ + public function rule(string $ruleName, array $arguments = []): Validatable + { + foreach ($this->rulesNamespaces as $namespace) { + try { + /** @var class-string $name */ + $name = $namespace . '\\' . ucfirst($ruleName); + /** @var Validatable $rule */ + $rule = $this + ->createReflectionClass($name, Validatable::class) + ->newInstanceArgs($arguments); + + return $rule; + } catch (ReflectionException $exception) { + continue; + } + } + + throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName)); + } + + /** + * Creates an exception. + * + * @param mixed $input + * @param mixed[] $extraParams + * + * @throws ComponentException + */ + public function exception(Validatable $validatable, $input, array $extraParams = []): ValidationException + { + $formatter = new Formatter($this->translator, $this->parameterStringifier); + $reflection = new ReflectionObject($validatable); + $ruleName = $reflection->getShortName(); + $params = ['input' => $input] + $extraParams + $this->extractPropertiesValues($validatable, $reflection); + $id = lcfirst($ruleName); + if ($validatable->getName() !== null) { + /*$id = */$params['name'] = $validatable->getName(); + } + $exceptionNamespace = str_replace('\\Rules', '\\Exceptions', $reflection->getNamespaceName()); + foreach (array_merge([$exceptionNamespace], $this->exceptionsNamespaces) as $namespace) { + try { + /** @var class-string $exceptionName */ + $exceptionName = $namespace . '\\' . $ruleName . 'Exception'; + + return $this->createValidationException( + $exceptionName, + $id, + $input, + $params, + $formatter + ); + } catch (ReflectionException $exception) { + continue; + } + } + + return new ValidationException($input, $id, $params, $formatter); + } + + /** + * Define the default instance of the Factory. + */ + public static function setDefaultInstance(self $defaultInstance): void + { + self::$defaultInstance = $defaultInstance; + } + + /** + * Creates a reflection based on class name. + * + * @param class-string $name + * @param class-string $parentName + * + * @throws InvalidClassException + * @throws ReflectionException + * + * @return ReflectionClass + */ + private function createReflectionClass(string $name, string $parentName): ReflectionClass + { + $reflection = new ReflectionClass($name); + if (!$reflection->isSubclassOf($parentName) && $parentName !== $name) { + throw new InvalidClassException(sprintf('"%s" must be an instance of "%s"', $name, $parentName)); + } + + if (!$reflection->isInstantiable()) { + throw new InvalidClassException(sprintf('"%s" must be instantiable', $name)); + } + + return $reflection; + } + + /** + * Creates a Validation exception. + * + * @param class-string $exceptionName + * + * @param mixed $input + * @param mixed[] $params + * + * @throws InvalidClassException + * @throws ReflectionException + */ + private function createValidationException( + string $exceptionName, + string $id, + $input, + array $params, + Formatter $formatter + ): ValidationException { + /** @var ValidationException $exception */ + $exception = $this + ->createReflectionClass($exceptionName, ValidationException::class) + ->newInstance($input, $id, $params, $formatter); + if (isset($params['template'])) { + $exception->updateTemplate($params['template']); + } + + return $exception; + } + + /** + * @param ReflectionObject|ReflectionClass $reflection + * @return mixed[] + */ + private function extractPropertiesValues(Validatable $validatable, ReflectionClass $reflection): array + { + $values = []; + foreach ($reflection->getProperties() as $property) { + $property->setAccessible(true); + + $propertyValue = $property->getValue($validatable); + if ($propertyValue === null) { + continue; + } + + $values[$property->getName()] = $propertyValue; + } + + $parentReflection = $reflection->getParentClass(); + if ($parentReflection !== false) { + return $values + $this->extractPropertiesValues($validatable, $parentReflection); + } + + return $values; + } +} diff --git a/cacme/vendor/workerman/validation/library/Helpers/CanCompareValues.php b/cacme/vendor/workerman/validation/library/Helpers/CanCompareValues.php new file mode 100644 index 0000000..28dd8fa --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Helpers/CanCompareValues.php @@ -0,0 +1,68 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Helpers; + +use Countable; +use DateTimeImmutable; +use DateTimeInterface; +use Throwable; + +use function is_numeric; +use function is_scalar; +use function is_string; +use function mb_strlen; + +/** + * Helps to deal with comparable values. + * + * @author Emmerson Siqueira + * @author Henrique Moody + */ +trait CanCompareValues +{ + /** + * Tries to convert a value into something that can be compared with PHP operators. + * + * @param mixed $value + * + * @return mixed + */ + private function toComparable($value) + { + if ($value instanceof Countable) { + return $value->count(); + } + + if ($value instanceof DateTimeInterface || !is_string($value) || is_numeric($value) || empty($value)) { + return $value; + } + + if (mb_strlen($value) === 1) { + return $value; + } + + try { + return new DateTimeImmutable($value); + } catch (Throwable $e) { + return $value; + } + } + + /** + * Returns whether the values can be compared or not. + * + * @param mixed $left + * @param mixed $right + */ + private function isAbleToCompareValues($left, $right): bool + { + return is_scalar($left) === is_scalar($right); + } +} diff --git a/cacme/vendor/workerman/validation/library/Helpers/CanValidateDateTime.php b/cacme/vendor/workerman/validation/library/Helpers/CanValidateDateTime.php new file mode 100644 index 0000000..306f419 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Helpers/CanValidateDateTime.php @@ -0,0 +1,86 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Helpers; + +use DateTime; +use DateTimeZone; + +use function checkdate; +use function date_default_timezone_get; +use function date_parse_from_format; +use function preg_match; + +/** + * Helper to handle date/time. + * + * @author Henrique Moody + */ +trait CanValidateDateTime +{ + /** + * Finds whether a value is a valid date/time in a specific format. + */ + private function isDateTime(string $format, string $value): bool + { + $exceptionalFormats = [ + 'c' => 'Y-m-d\TH:i:sP', + 'r' => 'D, d M Y H:i:s O', + ]; + + $format = $exceptionalFormats[$format] ?? $format; + + $info = date_parse_from_format($format, $value); + + if (!$this->isDateTimeParsable($info)) { + return false; + } + + if ($this->isDateFormat($format)) { + $formattedDate = DateTime::createFromFormat( + $format, + $value, + new DateTimeZone(date_default_timezone_get()) + ); + + if ($formattedDate === false || $value !== $formattedDate->format($format)) { + return false; + } + + return $this->isDateInformation($info); + } + + return true; + } + + /** + * @param mixed[] $info + */ + private function isDateTimeParsable(array $info): bool + { + return $info['error_count'] === 0 && $info['warning_count'] === 0; + } + + private function isDateFormat(string $format): bool + { + return preg_match('/[djSFmMnYy]/', $format) > 0; + } + + /** + * @param mixed[] $info + */ + private function isDateInformation(array $info): bool + { + if ($info['day']) { + return checkdate((int) $info['month'], $info['day'], (int) $info['year']); + } + + return checkdate($info['month'] ?: 1, 1, $info['year'] ?: 1); + } +} diff --git a/cacme/vendor/workerman/validation/library/Helpers/CanValidateIterable.php b/cacme/vendor/workerman/validation/library/Helpers/CanValidateIterable.php new file mode 100644 index 0000000..0de2c4e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Helpers/CanValidateIterable.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Helpers; + +use stdClass; +use Traversable; + +use function is_array; + +/** + * Helper to handle iterable values. + * + * @author Henrique Moody + */ +trait CanValidateIterable +{ + /** + * Returns whether the value is iterable or not. + * + * @param mixed $value + */ + public function isIterable($value): bool + { + return is_array($value) || $value instanceof stdClass || $value instanceof Traversable; + } +} diff --git a/cacme/vendor/workerman/validation/library/Helpers/CanValidateUndefined.php b/cacme/vendor/workerman/validation/library/Helpers/CanValidateUndefined.php new file mode 100644 index 0000000..019d089 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Helpers/CanValidateUndefined.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Helpers; + +use function in_array; + +/** + * Helper to identify values that Validation consider as "undefined". + * + * @author Henrique Moody + */ +trait CanValidateUndefined +{ + /** + * Finds whether the value is undefined or not. + * + * @param mixed $value + */ + private function isUndefined($value): bool + { + return in_array($value, [null, ''], true); + } +} diff --git a/cacme/vendor/workerman/validation/library/Helpers/CountryInfo.php b/cacme/vendor/workerman/validation/library/Helpers/CountryInfo.php new file mode 100644 index 0000000..094fcae --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Helpers/CountryInfo.php @@ -0,0 +1,54 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Helpers; + +use Respect\Validation\Exceptions\ComponentException; + +use function file_exists; +use function sprintf; + +final class CountryInfo +{ + /** + * @var mixed[] + */ + private $data; + + /** + * @var mixed[] + */ + private static $runtimeCache = []; + + public function __construct(string $countryCode) + { + if (!isset(static::$runtimeCache[$countryCode])) { + $filename = __DIR__ . '/../../data/iso_3166-2/' . $countryCode . '.php'; + if (!file_exists($filename)) { + throw new ComponentException(sprintf('"%s" is not a supported country code', $countryCode)); + } + static::$runtimeCache[$countryCode] = require $filename; + } + + $this->data = static::$runtimeCache[$countryCode]; + } + + public function getCountry(): string + { + return $this->data['country']; + } + + /** + * @return string[] + */ + public function getSubdivisions(): array + { + return $this->data['subdivisions']; + } +} diff --git a/cacme/vendor/workerman/validation/library/Helpers/DomainInfo.php b/cacme/vendor/workerman/validation/library/Helpers/DomainInfo.php new file mode 100644 index 0000000..502da83 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Helpers/DomainInfo.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Helpers; + +use function file_exists; +use function mb_strtoupper; + +final class DomainInfo +{ + /** + * @var mixed[] + */ + private $data; + + /** + * @var mixed[] + */ + private static $runtimeCache = []; + + public function __construct(string $tld) + { + $tld = mb_strtoupper($tld); + + if (!isset(static::$runtimeCache[$tld])) { + $filename = __DIR__ . '/../../data/domain/public-suffix/' . $tld . '.php'; + static::$runtimeCache[$tld] = file_exists($filename) ? require $filename : []; + } + + $this->data = static::$runtimeCache[$tld]; + } + + /** + * @return array + */ + public function getPublicSuffixes(): array + { + return $this->data; + } +} diff --git a/cacme/vendor/workerman/validation/library/Message/Formatter.php b/cacme/vendor/workerman/validation/library/Message/Formatter.php new file mode 100644 index 0000000..e35d1a2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Message/Formatter.php @@ -0,0 +1,54 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message; + +use function call_user_func; +use function preg_replace_callback; +use function Respect\Stringifier\stringify; + +final class Formatter +{ + /** + * @var callable + */ + private $translator; + + /** + * @var ParameterStringifier + */ + private $parameterStringifier; + + public function __construct(callable $translator, ParameterStringifier $parameterStringifier) + { + $this->translator = $translator; + $this->parameterStringifier = $parameterStringifier; + } + + /** + * @param mixed $input + * @param mixed[] $parameters + */ + public function format(string $template, $input, array $parameters): string + { + $parameters['name'] = $parameters['name'] ?? stringify($input); + + return preg_replace_callback( + '/{{(\w+)}}/', + function ($match) use ($parameters) { + if (!isset($parameters[$match[1]])) { + return $match[0]; + } + + return $this->parameterStringifier->stringify($match[1], $parameters[$match[1]]); + }, + call_user_func($this->translator, $template) + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Message/ParameterStringifier.php b/cacme/vendor/workerman/validation/library/Message/ParameterStringifier.php new file mode 100644 index 0000000..90fb60b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Message/ParameterStringifier.php @@ -0,0 +1,18 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message; + +interface ParameterStringifier +{ + /** + * @param mixed $value + */ + public function stringify(string $name, $value): string; +} diff --git a/cacme/vendor/workerman/validation/library/Message/Stringifier/KeepOriginalStringName.php b/cacme/vendor/workerman/validation/library/Message/Stringifier/KeepOriginalStringName.php new file mode 100644 index 0000000..808d224 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Message/Stringifier/KeepOriginalStringName.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Stringifier; + +use Respect\Validation\Message\ParameterStringifier; + +use function is_string; +use function Respect\Stringifier\stringify; + +final class KeepOriginalStringName implements ParameterStringifier +{ + /** + * {@inheritDoc} + */ + public function stringify(string $name, $value): string + { + if ($name === 'name' && is_string($value)) { + return $value; + } + + return stringify($value); + } +} diff --git a/cacme/vendor/workerman/validation/library/NonNegatable.php b/cacme/vendor/workerman/validation/library/NonNegatable.php new file mode 100644 index 0000000..7fa5626 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/NonNegatable.php @@ -0,0 +1,18 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation; + +/** Interface for validation rules */ +/** + * @author Alexandre Gomes Gaigalas + */ +interface NonNegatable +{ +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractAge.php b/cacme/vendor/workerman/validation/library/Rules/AbstractAge.php new file mode 100644 index 0000000..d8a7886 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractAge.php @@ -0,0 +1,98 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CanValidateDateTime; + +use function date; +use function date_parse_from_format; +use function is_scalar; +use function strtotime; +use function vsprintf; + +/** + * Abstract class to validate ages. + * + * @author Henrique Moody + */ +abstract class AbstractAge extends AbstractRule +{ + use CanValidateDateTime; + + /** + * @var int + */ + private $age; + + /** + * @var string|null + */ + private $format; + + /** + * @var int + */ + private $baseDate; + + /** + * Should compare the current base date with the given one. + * + * The dates are represented as integers in the format "Ymd". + */ + abstract protected function compare(int $baseDate, int $givenDate): bool; + + /** + * Initializes the rule. + */ + public function __construct(int $age, ?string $format = null) + { + $this->age = $age; + $this->format = $format; + $this->baseDate = (int) date('Ymd') - $this->age * 10000; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + if ($this->format === null) { + return $this->isValidWithoutFormat((string) $input); + } + + return $this->isValidWithFormat($this->format, (string) $input); + } + + private function isValidWithoutFormat(string $dateTime): bool + { + $timestamp = strtotime($dateTime); + if ($timestamp === false) { + return false; + } + + return $this->compare($this->baseDate, (int) date('Ymd', $timestamp)); + } + + private function isValidWithFormat(string $format, string $dateTime): bool + { + if (!$this->isDateTime($format, $dateTime)) { + return false; + } + + return $this->compare( + $this->baseDate, + (int) vsprintf('%d%02d%02d', date_parse_from_format($format, $dateTime)) + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractComparison.php b/cacme/vendor/workerman/validation/library/Rules/AbstractComparison.php new file mode 100644 index 0000000..c65deb9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractComparison.php @@ -0,0 +1,60 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CanCompareValues; + +/** + * Abstract class to help on creating rules that compare value. + * + * @author Henrique Moody + */ +abstract class AbstractComparison extends AbstractRule +{ + use CanCompareValues; + + /** + * @var mixed + */ + private $compareTo; + + /** + * Compare both values and return whether the comparison is valid or not. + * + * @param mixed $left + * @param mixed $right + */ + abstract protected function compare($left, $right): bool; + + /** + * Initializes the rule by setting the value to be compared to the input. + * + * @param mixed $maxValue + */ + public function __construct($maxValue) + { + $this->compareTo = $maxValue; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + $left = $this->toComparable($input); + $right = $this->toComparable($this->compareTo); + + if (!$this->isAbleToCompareValues($left, $right)) { + return false; + } + + return $this->compare($left, $right); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractComposite.php b/cacme/vendor/workerman/validation/library/Rules/AbstractComposite.php new file mode 100644 index 0000000..bd8126b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractComposite.php @@ -0,0 +1,150 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\NestedValidationException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Validatable; + +use function array_filter; +use function array_map; + +/** + * Abstract class for rules that are composed by other rules. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Wojciech Frącz + */ +abstract class AbstractComposite extends AbstractRule +{ + /** + * @var Validatable[] + */ + private $rules = []; + + /** + * Initializes the rule adding other rules to the stack. + */ + public function __construct(Validatable ...$rules) + { + $this->rules = $rules; + } + + /** + * {@inheritDoc} + */ + public function setName(string $name): Validatable + { + $parentName = $this->getName(); + foreach ($this->rules as $rule) { + $ruleName = $rule->getName(); + if ($ruleName && $parentName !== $ruleName) { + continue; + } + + $rule->setName($name); + } + + return parent::setName($name); + } + + public function setDefault(string $default, bool $defaultType=false): Validatable + { + $parentDefault = $this->getDefault(); + foreach ($this->rules as $rule) { + $ruleDefault = $rule->getDefault(); + if ($ruleDefault && $parentDefault !== $ruleDefault) { + continue; + } + $rule->setDefault($default, $defaultType); + } + return parent::setDefault($default, $defaultType); + } + /** + * Append a rule into the stack of rules. + * + * @return AbstractComposite + */ + public function addRule(Validatable $rule): self + { + if ($this->shouldHaveNameOverwritten($rule) && $this->getName() !== null) { + $rule->setName($this->getName()); + } + + $this->rules[] = $rule; + + return $this; + } + + /** + * Returns all the rules in the stack. + * + * @return Validatable[] + */ + public function getRules(): array + { + return $this->rules; + } + + /** + * Returns all the exceptions throw when asserting all rules. + * + * @param mixed $input + * + * @return ValidationException[] + */ + protected function getAllThrownExceptions($input): array + { + return array_filter( + array_map( + function (Validatable $rule) use ($input): ?ValidationException { + try { + $rule->assert($input); + } catch (ValidationException $exception) { + $this->updateExceptionTemplate($exception); + + return $exception; + } + + return null; + }, + $this->getRules() + ) + ); + } + + private function shouldHaveNameOverwritten(Validatable $rule): bool + { + return $this->hasName($this) && !$this->hasName($rule); + } + + private function hasName(Validatable $rule): bool + { + return $rule->getName() !== null; + } + + private function updateExceptionTemplate(ValidationException $exception): void + { + if ($this->template === null || $exception->hasCustomTemplate()) { + return; + } + + $exception->updateTemplate($this->template); + + if (!$exception instanceof NestedValidationException) { + return; + } + + foreach ($exception->getChildren() as $childException) { + $this->updateExceptionTemplate($childException); + } + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractEnvelope.php b/cacme/vendor/workerman/validation/library/Rules/AbstractEnvelope.php new file mode 100644 index 0000000..650e48e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractEnvelope.php @@ -0,0 +1,61 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Validatable; + +/** + * Abstract class that creates an envelope around another rule. + * + * This class is usefull when you want to create rules that use other rules, but + * having an custom message. + * + * @author Henrique Moody + */ +abstract class AbstractEnvelope extends AbstractRule +{ + /** + * @var Validatable + */ + private $validatable; + + /** + * @var mixed[] + */ + private $parameters; + + /** + * Initializes the rule. + * + * @param mixed[] $parameters + */ + public function __construct(Validatable $validatable, array $parameters = []) + { + $this->validatable = $validatable; + $this->parameters = $parameters; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $this->validatable->validate($input); + } + + /** + * {@inheritDoc} + */ + public function reportError($input, array $extraParameters = []): ValidationException + { + return parent::reportError($input, $extraParameters + $this->parameters); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractFilterRule.php b/cacme/vendor/workerman/validation/library/Rules/AbstractFilterRule.php new file mode 100644 index 0000000..2c658a0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractFilterRule.php @@ -0,0 +1,61 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function implode; +use function is_scalar; +use function str_replace; +use function str_split; + +/** + * @author Henrique Moody + * @author Nick Lombard + */ +abstract class AbstractFilterRule extends AbstractRule +{ + /** + * @var string + */ + private $additionalChars; + + abstract protected function validateFilteredInput(string $input): bool; + + /** + * Initializes the rule with a list of characters to be ignored by the validation. + */ + public function __construct(string ...$additionalChars) + { + $this->additionalChars = implode($additionalChars); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $stringInput = (string) $input; + if ($stringInput === '') { + return false; + } + + $filteredInput = $this->filter($stringInput); + + return $filteredInput === '' || $this->validateFilteredInput($filteredInput); + } + + private function filter(string $input): string + { + return str_replace(str_split($this->additionalChars), '', $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractRelated.php b/cacme/vendor/workerman/validation/library/Rules/AbstractRelated.php new file mode 100644 index 0000000..8767552 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractRelated.php @@ -0,0 +1,154 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\NestedValidationException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Validatable; + +use function is_scalar; + +/** + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Nick Lombard + */ +abstract class AbstractRelated extends AbstractRule +{ + /** + * @var bool + */ + private $mandatory = true; + + /** + * @var mixed + */ + private $reference; + + /** + * @var Validatable|null + */ + private $rule; + + /** + * @param mixed $input + */ + abstract public function hasReference($input): bool; + + /** + * @param mixed $input + * + * @return mixed + */ + abstract public function getReferenceValue($input); + + /** + * @param mixed $reference + */ + public function __construct($reference, ?Validatable $rule = null, bool $mandatory = true) + { + $this->reference = $reference; + $this->rule = $rule; + $this->mandatory = $mandatory; + + if ($rule && $rule->getName() !== null) { + $this->setName($rule->getName()); + } elseif (is_scalar($reference)) { + $this->setName((string) $reference); + } + } + + /** + * @return mixed + */ + public function getReference() + { + return $this->reference; + } + + public function isMandatory(): bool + { + return $this->mandatory; + } + + /** + * {@inheritDoc} + */ + public function setName(string $name): Validatable + { + parent::setName($name); + + if ($this->rule instanceof Validatable) { + $this->rule->setName($name); + } + + return $this; + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $hasReference = $this->hasReference($input); + if ($this->mandatory && !$hasReference) { + throw $this->reportError($input, ['hasReference' => false]); + } + + if ($this->rule === null || !$hasReference) { + return; + } + + try { + $this->rule->assert($this->getReferenceValue($input)); + } catch (ValidationException $validationException) { + /** @var NestedValidationException $nestedValidationException */ + $nestedValidationException = $this->reportError($this->reference, ['hasReference' => true]); + $nestedValidationException->addChild($validationException); + + throw $nestedValidationException; + } + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + $hasReference = $this->hasReference($input); + if ($this->mandatory && !$hasReference) { + throw $this->reportError($input, ['hasReference' => false]); + } + + if ($this->rule === null || !$hasReference) { + return; + } + + $this->rule->check($this->getReferenceValue($input)); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + $hasReference = $this->hasReference($input); + if ($this->mandatory && !$hasReference) { + return false; + } + + if ($this->rule === null || !$hasReference) { + return true; + } + + return $this->rule->validate($this->getReferenceValue($input)); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractRule.php b/cacme/vendor/workerman/validation/library/Rules/AbstractRule.php new file mode 100644 index 0000000..4211df2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractRule.php @@ -0,0 +1,126 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Factory; +use Respect\Validation\Validatable; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Nick Lombard + * @author Vicente Mendoza + */ +abstract class AbstractRule implements Validatable +{ + /** + * @var string|null + */ + protected $default; + /** + * @var bool|false + */ + protected $defaultType; + /** + * @var string|null + */ + protected $name; + + /** + * @var string|null + */ + protected $template; + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if ($this->validate($input)) { + return; + } + + throw $this->reportError($input); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + $this->assert($input); + } + + /** + * {@inheritDoc} + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function reportError($input, array $extraParams = []): ValidationException + { + return Factory::getDefaultInstance()->exception($this, $input, $extraParams); + } + + /** + * {@inheritDoc} + */ + public function setName(string $name): Validatable + { + $this->name = $name; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function setTemplate(string $template): Validatable + { + $this->template = $template; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function getDefault(): ?string + { + return $this->default; + } + /** + * {@inheritDoc} + */ + public function getDefaultType(): ?bool + { + return $this->defaultType; + } + public function setDefault(string $default, bool $defaultType=false): Validatable + { + $this->default = $default; + $this->defaultType = $defaultType; + return $this; + } + + /** + * @param mixed$input + */ + public function __invoke($input): bool + { + return $this->validate($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractSearcher.php b/cacme/vendor/workerman/validation/library/Rules/AbstractSearcher.php new file mode 100644 index 0000000..f73d963 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractSearcher.php @@ -0,0 +1,50 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CanValidateUndefined; + +use function in_array; +use function is_scalar; +use function mb_strtoupper; + +/** + * Abstract class for searches into arrays. + * + * @author Henrique Moody + */ +abstract class AbstractSearcher extends AbstractRule +{ + use CanValidateUndefined; + + /** + * @param mixed $input + * @return mixed[] + */ + abstract protected function getDataSource($input = null): array; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + $dataSource = $this->getDataSource($input); + + if ($this->isUndefined($input) && empty($dataSource)) { + return true; + } + + if (!is_scalar($input)) { + return false; + } + + return in_array(mb_strtoupper((string) $input), $dataSource, true); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AbstractWrapper.php b/cacme/vendor/workerman/validation/library/Rules/AbstractWrapper.php new file mode 100644 index 0000000..75a5738 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AbstractWrapper.php @@ -0,0 +1,68 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Validatable; + +/** + * Abstract class to help on creating rules that wrap rules. + * + * @author Alasdair North + * @author Henrique Moody + */ +abstract class AbstractWrapper extends AbstractRule +{ + /** + * @var Validatable + */ + private $validatable; + + /** + * Initializes the rule. + */ + public function __construct(Validatable $validatable) + { + $this->validatable = $validatable; + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $this->validatable->assert($input); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + $this->validatable->check($input); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $this->validatable->validate($input); + } + + /** + * {@inheritDoc} + */ + public function setName(string $name): Validatable + { + $this->validatable->setName($name); + + return parent::setName($name); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AllOf.php b/cacme/vendor/workerman/validation/library/Rules/AllOf.php new file mode 100644 index 0000000..ebbc42c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AllOf.php @@ -0,0 +1,67 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\AllOfException; + +use function count; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +class AllOf extends AbstractComposite +{ + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $exceptions = $this->getAllThrownExceptions($input); + $numRules = count($this->getRules()); + $numExceptions = count($exceptions); + $summary = [ + 'total' => $numRules, + 'failed' => $numExceptions, + 'passed' => $numRules - $numExceptions, + ]; + if (!empty($exceptions)) { + /** @var AllOfException $allOfException */ + $allOfException = $this->reportError($input, $summary); + $allOfException->addChildren($exceptions); + + throw $allOfException; + } + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + foreach ($this->getRules() as $rule) { + $rule->check($input); + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + foreach ($this->getRules() as $rule) { + if (!$rule->validate($input)) { + return false; + } + } + + return true; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Alnum.php b/cacme/vendor/workerman/validation/library/Rules/Alnum.php new file mode 100644 index 0000000..c52dd9b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Alnum.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_alnum; + +/** + * Validates whether the input is alphanumeric or not. + * + * Alphanumeric is a combination of alphabetic (a-z and A-Z) and numeric (0-9) + * characters. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Nick Lombard + */ +final class Alnum extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_alnum($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Alpha.php b/cacme/vendor/workerman/validation/library/Rules/Alpha.php new file mode 100644 index 0000000..c218768 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Alpha.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_alpha; + +/** + * Validates whether the input contains only alphabetic characters. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Nick Lombard + */ +final class Alpha extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_alpha($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AlwaysInvalid.php b/cacme/vendor/workerman/validation/library/Rules/AlwaysInvalid.php new file mode 100644 index 0000000..b3eb773 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AlwaysInvalid.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates any input as invalid. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class AlwaysInvalid extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AlwaysValid.php b/cacme/vendor/workerman/validation/library/Rules/AlwaysValid.php new file mode 100644 index 0000000..c8a8212 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AlwaysValid.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates any input as valid. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class AlwaysValid extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return true; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/AnyOf.php b/cacme/vendor/workerman/validation/library/Rules/AnyOf.php new file mode 100644 index 0000000..ddf213c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/AnyOf.php @@ -0,0 +1,78 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\AnyOfException; +use Respect\Validation\Exceptions\ValidationException; + +use function count; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class AnyOf extends AbstractComposite +{ + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $validators = $this->getRules(); + $exceptions = $this->getAllThrownExceptions($input); + $numRules = count($validators); + $numExceptions = count($exceptions); + if ($numExceptions === $numRules) { + /** @var AnyOfException $anyOfException */ + $anyOfException = $this->reportError($input); + $anyOfException->addChildren($exceptions); + + throw $anyOfException; + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + foreach ($this->getRules() as $v) { + if ($v->validate($input)) { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + foreach ($this->getRules() as $v) { + try { + $v->check($input); + + return; + } catch (ValidationException $e) { + if (!isset($firstException)) { + $firstException = $e; + } + } + } + + if (isset($firstException)) { + throw $firstException; + } + + throw $this->reportError($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/ArrayType.php b/cacme/vendor/workerman/validation/library/Rules/ArrayType.php new file mode 100644 index 0000000..cbfe7d9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/ArrayType.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_array; + +/** + * Validates whether the type of an input is array. + * + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + * @author João Torquato + */ +final class ArrayType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_array($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/ArrayVal.php b/cacme/vendor/workerman/validation/library/Rules/ArrayVal.php new file mode 100644 index 0000000..53bd4e8 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/ArrayVal.php @@ -0,0 +1,35 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use ArrayAccess; +use SimpleXMLElement; + +use function is_array; + +/** + * Validates if the input is an array or if the input can be used as an array. + * + * Instance of `ArrayAccess` or `SimpleXMLElement` are also considered as valid. + * + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class ArrayVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_array($input) || $input instanceof ArrayAccess || $input instanceof SimpleXMLElement; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Attribute.php b/cacme/vendor/workerman/validation/library/Rules/Attribute.php new file mode 100644 index 0000000..e1873f1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Attribute.php @@ -0,0 +1,53 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use ReflectionException; +use ReflectionProperty; +use Respect\Validation\Validatable; + +use function is_object; +use function property_exists; + +/** + * Validates an object attribute, event private ones. + * + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class Attribute extends AbstractRelated +{ + public function __construct(string $reference, ?Validatable $rule = null, bool $mandatory = true) + { + parent::__construct($reference, $rule, $mandatory); + } + + /** + * {@inheritDoc} + * + * @throws ReflectionException + */ + public function getReferenceValue($input) + { + $propertyMirror = new ReflectionProperty($input, (string) $this->getReference()); + $propertyMirror->setAccessible(true); + + return $propertyMirror->getValue($input); + } + + /** + * {@inheritDoc} + */ + public function hasReference($input): bool + { + return is_object($input) && property_exists($input, (string) $this->getReference()); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Base.php b/cacme/vendor/workerman/validation/library/Rules/Base.php new file mode 100644 index 0000000..03f6d77 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Base.php @@ -0,0 +1,64 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function is_null; +use function mb_strlen; +use function mb_substr; +use function preg_match; +use function sprintf; + +/** + * Validate numbers in any base, even with non regular bases. + * + * @author Carlos André Ferrari + * @author Henrique Moody + * @author William Espindola + */ +final class Base extends AbstractRule +{ + /** + * @var string + */ + private $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + /** + * @var int + */ + private $base; + + /** + * Initializes the Base rule. + */ + public function __construct(int $base, ?string $chars = null) + { + if (!is_null($chars)) { + $this->chars = $chars; + } + + $max = mb_strlen($this->chars); + if ($base > $max) { + throw new ComponentException(sprintf('a base between 1 and %s is required', $max)); + } + $this->base = $base; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + $valid = mb_substr($this->chars, 0, $this->base); + + return (bool) preg_match('@^[' . $valid . ']+$@', (string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Base64.php b/cacme/vendor/workerman/validation/library/Rules/Base64.php new file mode 100644 index 0000000..11a0707 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Base64.php @@ -0,0 +1,40 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function mb_strlen; +use function preg_match; + +/** + * Validate if a string is Base64-encoded. + * + * @author Henrique Moody + * @author Jens Segers + * @author William Espindola + */ +final class Base64 extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + if (!preg_match('#^[A-Za-z0-9+/\n\r]+={0,2}$#', $input)) { + return false; + } + + return mb_strlen($input) % 4 === 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Between.php b/cacme/vendor/workerman/validation/library/Rules/Between.php new file mode 100644 index 0000000..8e17c29 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Between.php @@ -0,0 +1,50 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Helpers\CanCompareValues; + +/** + * Validates whether the input is between two other values. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class Between extends AbstractEnvelope +{ + use CanCompareValues; + + /** + * Initializes the rule. + * + * @param mixed $minValue + * @param mixed $maxValue + * + * @throws ComponentException + */ + public function __construct($minValue, $maxValue) + { + if ($this->toComparable($minValue) >= $this->toComparable($maxValue)) { + throw new ComponentException('Minimum cannot be less than or equals to maximum'); + } + + parent::__construct( + new AllOf( + new Min($minValue), + new Max($maxValue) + ), + [ + 'minValue' => $minValue, + 'maxValue' => $maxValue, + ] + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/BoolType.php b/cacme/vendor/workerman/validation/library/Rules/BoolType.php new file mode 100644 index 0000000..0f32be5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/BoolType.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_bool; + +/** + * Validates whether the type of the input is boolean. + * + * @author Devin Torres + * @author Henrique Moody + */ +final class BoolType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_bool($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/BoolVal.php b/cacme/vendor/workerman/validation/library/Rules/BoolVal.php new file mode 100644 index 0000000..b9cef69 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/BoolVal.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function filter_var; +use function is_bool; + +use const FILTER_NULL_ON_FAILURE; +use const FILTER_VALIDATE_BOOLEAN; + +/** + * Validates if the input results in a boolean value. + * + * @author Emmerson Siqueira + * @author Henrique Moody + * @author William Espindola + */ +final class BoolVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_bool(filter_var($input, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Bsn.php b/cacme/vendor/workerman/validation/library/Rules/Bsn.php new file mode 100644 index 0000000..a5cb512 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Bsn.php @@ -0,0 +1,55 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_digit; +use function intval; +use function is_scalar; +use function mb_strlen; +use function strval; + +/** + * Validates a Dutch citizen service number (BSN). + * + * @see https://nl.wikipedia.org/wiki/Burgerservicenummer + * + * @author Henrique Moody + * @author Ronald Drenth + * @author William Espindola + */ +final class Bsn extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $input = (string) $input; + + if (!ctype_digit($input)) { + return false; + } + + if (mb_strlen(strval($input)) !== 9) { + return false; + } + + $sum = -1 * intval($input[8]); + for ($i = 9; $i > 1; --$i) { + $sum += $i * intval($input[9 - $i]); + } + + return $sum !== 0 && $sum % 11 === 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Call.php b/cacme/vendor/workerman/validation/library/Rules/Call.php new file mode 100644 index 0000000..9403239 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Call.php @@ -0,0 +1,107 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Validatable; +use Throwable; + +use function call_user_func; +use function restore_error_handler; +use function set_error_handler; + +/** + * Validates the return of a callable for a given input. + * + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class Call extends AbstractRule +{ + /** + * @var callable + */ + private $callable; + + /** + * @var Validatable + */ + private $rule; + + /** + * Initializes the rule with the callable to be executed after the input is passed. + */ + public function __construct(callable $callable, Validatable $rule) + { + $this->callable = $callable; + $this->rule = $rule; + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $this->setErrorHandler($input); + + try { + $this->rule->assert(call_user_func($this->callable, $input)); + } catch (ValidationException $exception) { + throw $exception; + } catch (Throwable $throwable) { + throw $this->reportError($input); + } finally { + restore_error_handler(); + } + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + $this->setErrorHandler($input); + + try { + $this->rule->check(call_user_func($this->callable, $input)); + } catch (ValidationException $exception) { + throw $exception; + } catch (Throwable $throwable) { + throw $this->reportError($input); + } finally { + restore_error_handler(); + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + try { + $this->check($input); + } catch (ValidationException $exception) { + return false; + } + + return true; + } + + /** + * @param mixed $input + */ + private function setErrorHandler($input): void + { + set_error_handler(function () use ($input): void { + throw $this->reportError($input); + }); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/CallableType.php b/cacme/vendor/workerman/validation/library/Rules/CallableType.php new file mode 100644 index 0000000..0fa9eb1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/CallableType.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_callable; + +/** + * Validates whether the pseudo-type of the input is callable. + * + * @author Henrique Moody + */ +final class CallableType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_callable($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Callback.php b/cacme/vendor/workerman/validation/library/Rules/Callback.php new file mode 100644 index 0000000..3c057a2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Callback.php @@ -0,0 +1,67 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_merge; +use function call_user_func_array; +use function count; + +/** + * Validates the input using the return of a given callable. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class Callback extends AbstractRule +{ + /** + * @var callable + */ + private $callback; + + /** + * @var mixed[] + */ + private $arguments; + + /** + * Initializes the rule. + * + * @param mixed ...$arguments + */ + public function __construct(callable $callback, ...$arguments) + { + $this->callback = $callback; + $this->arguments = $arguments; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return (bool) call_user_func_array($this->callback, $this->getArguments($input)); + } + + /** + * @param mixed $input + * @return mixed[] + */ + private function getArguments($input): array + { + $arguments = [$input]; + if (count($this->arguments) === 0) { + return $arguments; + } + + return array_merge($arguments, $this->arguments); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Charset.php b/cacme/vendor/workerman/validation/library/Rules/Charset.php new file mode 100644 index 0000000..00640e2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Charset.php @@ -0,0 +1,55 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_diff; +use function in_array; +use function mb_detect_encoding; +use function mb_list_encodings; + +/** + * Validates if a string is in a specific charset. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author William Espindola + */ +final class Charset extends AbstractRule +{ + /** + * @var string[] + */ + private $charset; + + /** + * Initializes the rule. + * + * @throws ComponentException + */ + public function __construct(string ...$charset) + { + $available = mb_list_encodings(); + if (!empty(array_diff($charset, $available))) { + throw new ComponentException('Invalid charset'); + } + + $this->charset = $charset; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return in_array(mb_detect_encoding($input, $this->charset, true), $this->charset, true); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Cnh.php b/cacme/vendor/workerman/validation/library/Rules/Cnh.php new file mode 100644 index 0000000..4b180fd --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Cnh.php @@ -0,0 +1,59 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function mb_strlen; +use function preg_replace; + +/** + * Validates a Brazilian driver's license. + * + * @author Gabriel Pedro + * @author Henrique Moody + * @author Kinn Coelho Julião + * @author William Espindola + */ +final class Cnh extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + // Canonicalize input + $input = (string) preg_replace('{\D}', '', (string) $input); + + // Validate length and invalid numbers + if (mb_strlen($input) != 11 || ((int) $input === 0)) { + return false; + } + + // Validate check digits using a modulus 11 algorithm + for ($c = $s1 = $s2 = 0, $p = 9; $c < 9; $c++, $p--) { + $s1 += (int) $input[$c] * $p; + $s2 += (int) $input[$c] * (10 - $p); + } + + $dv1 = $s1 % 11; + if ($input[9] != ($dv1 > 9) ? 0 : $dv1) { + return false; + } + + $dv2 = $s2 % 11 - ($dv1 > 9 ? 2 : 0); + $check = $dv2 < 0 ? $dv2 + 11 : ($dv2 > 9 ? 0 : $dv2); + + return $input[10] == $check; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Cnpj.php b/cacme/vendor/workerman/validation/library/Rules/Cnpj.php new file mode 100644 index 0000000..78081f2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Cnpj.php @@ -0,0 +1,83 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_map; +use function array_sum; +use function count; +use function is_scalar; +use function preg_replace; +use function str_split; + +/** + * Validates if the input is a Brazilian National Registry of Legal Entities (CNPJ) number. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Jayson Reis + * @author Nick Lombard + * @author Renato Moura + * @author William Espindola + */ +final class Cnpj extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + // Code ported from jsfromhell.com + $bases = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + $digits = $this->getDigits((string) $input); + + if (array_sum($digits) < 1) { + return false; + } + + if (count($digits) !== 14) { + return false; + } + + $n = 0; + for ($i = 0; $i < 12; ++$i) { + $n += $digits[$i] * $bases[$i + 1]; + } + + if ($digits[12] != (($n %= 11) < 2 ? 0 : 11 - $n)) { + return false; + } + + $n = 0; + for ($i = 0; $i <= 12; ++$i) { + $n += $digits[$i] * $bases[$i]; + } + + $check = ($n %= 11) < 2 ? 0 : 11 - $n; + + return $digits[13] == $check; + } + + /** + * @return int[] + */ + private function getDigits(string $input): array + { + return array_map( + 'intval', + str_split( + (string) preg_replace('/\D/', '', $input) + ) + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Consonant.php b/cacme/vendor/workerman/validation/library/Rules/Consonant.php new file mode 100644 index 0000000..f765ef0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Consonant.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function preg_match; + +/** + * Validates if the input contains only consonants. + * + * @author Danilo Correa + * @author Henrique Moody + * @author Nick Lombard + */ +final class Consonant extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return preg_match('/^(\s|[b-df-hj-np-tv-zB-DF-HJ-NP-TV-Z])*$/', $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Contains.php b/cacme/vendor/workerman/validation/library/Rules/Contains.php new file mode 100644 index 0000000..0a92b92 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Contains.php @@ -0,0 +1,78 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function in_array; +use function is_array; +use function is_scalar; +use function mb_stripos; +use function mb_strpos; + +/** + * Validates if the input contains some value. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Marcelo Araujo + * @author William Espindola + */ +final class Contains extends AbstractRule +{ + /** + * @var mixed + */ + private $containsValue; + + /** + * @var bool + */ + private $identical; + + /** + * Initializes the Contains rule. + * + * @param mixed $containsValue Value that will be sought + * @param bool $identical Defines whether the value is identical, default is false + */ + public function __construct($containsValue, bool $identical = false) + { + $this->containsValue = $containsValue; + $this->identical = $identical; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_array($input)) { + return in_array($this->containsValue, $input, $this->identical); + } + + if (!is_scalar($input) || !is_scalar($this->containsValue)) { + return false; + } + + return $this->validateString((string) $input, (string) $this->containsValue); + } + + private function validateString(string $haystack, string $needle): bool + { + if ($needle === '') { + return false; + } + + if ($this->identical) { + return mb_strpos($haystack, $needle) !== false; + } + + return mb_stripos($haystack, $needle) !== false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/ContainsAny.php b/cacme/vendor/workerman/validation/library/Rules/ContainsAny.php new file mode 100644 index 0000000..87ec494 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/ContainsAny.php @@ -0,0 +1,50 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_map; + +/** + * Validates if the input contains at least one of defined values + * + * @author Henrique Moody + * @author Kirill Dlussky + */ +final class ContainsAny extends AbstractEnvelope +{ + /** + * Initializes the rule. + * + * @param mixed[] $needles At least one of the values provided must be found in input string or array + * @param bool $identical Defines whether the value should be compared strictly, when validating array + */ + public function __construct(array $needles, bool $identical = false) + { + parent::__construct( + new AnyOf(...$this->getRules($needles, $identical)), + ['needles' => $needles] + ); + } + + /** + * @param mixed[] $needles + * + * @return Contains[] + */ + private function getRules(array $needles, bool $identical): array + { + return array_map( + static function ($needle) use ($identical): Contains { + return new Contains($needle, $identical); + }, + $needles + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Control.php b/cacme/vendor/workerman/validation/library/Rules/Control.php new file mode 100644 index 0000000..1190550 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Control.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_cntrl; + +/** + * Validates if all of the characters in the provided string, are control characters. + * + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + * @author Nick Lombard + */ +final class Control extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_cntrl($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Countable.php b/cacme/vendor/workerman/validation/library/Rules/Countable.php new file mode 100644 index 0000000..8f2d8d6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Countable.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Countable as CountableInterface; + +use function is_array; + +/** + * Validates if the input is countable. + * + * @author Henrique Moody + * @author João Torquato + * @author William Espindola + */ +final class Countable extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_array($input) || $input instanceof CountableInterface; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/CountryCode.php b/cacme/vendor/workerman/validation/library/Rules/CountryCode.php new file mode 100644 index 0000000..e9b90d2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/CountryCode.php @@ -0,0 +1,375 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_column; +use function array_keys; +use function implode; +use function sprintf; + +/** + * Validates whether the input is a country code in ISO 3166-1 standard. + * + * This rule supports the three sets of country codes (alpha-2, alpha-3, and numeric). + * + * @author Alexandre Gomes Gaigalas + * @author Felipe Martins + * @author Henrique Moody + * @author William Espindola + */ +final class CountryCode extends AbstractSearcher +{ + /** + * The ISO representation of a country code. + */ + public const ALPHA2 = 'alpha-2'; + + /** + * The ISO3 representation of a country code. + */ + public const ALPHA3 = 'alpha-3'; + + /** + * The ISO-number representation of a country code. + */ + public const NUMERIC = 'numeric'; + + /** + * Position of the indexes of each set in the list of country codes. + */ + private const SET_INDEXES = [ + self::ALPHA2 => 0, + self::ALPHA3 => 1, + self::NUMERIC => 2, + ]; + + /** + * @see https://salsa.debian.org/iso-codes-team/iso-codes + */ + private const COUNTRY_CODES = [ + // begin of auto-generated code + ['AD', 'AND', '020'], // Andorra + ['AE', 'ARE', '784'], // United Arab Emirates + ['AF', 'AFG', '004'], // Afghanistan + ['AG', 'ATG', '028'], // Antigua and Barbuda + ['AI', 'AFI', '262'], // French Afars and Issas + ['AI', 'AIA', '660'], // Anguilla + ['AL', 'ALB', '008'], // Albania + ['AM', 'ARM', '051'], // Armenia + ['AN', 'ANT', '530'], // Netherlands Antilles + ['AO', 'AGO', '024'], // Angola + ['AQ', 'ATA', '010'], // Antarctica + ['AR', 'ARG', '032'], // Argentina + ['AS', 'ASM', '016'], // American Samoa + ['AT', 'AUT', '040'], // Austria + ['AU', 'AUS', '036'], // Australia + ['AW', 'ABW', '533'], // Aruba + ['AX', 'ALA', '248'], // Åland Islands + ['AZ', 'AZE', '031'], // Azerbaijan + ['BA', 'BIH', '070'], // Bosnia and Herzegovina + ['BB', 'BRB', '052'], // Barbados + ['BD', 'BGD', '050'], // Bangladesh + ['BE', 'BEL', '056'], // Belgium + ['BF', 'BFA', '854'], // Burkina Faso + ['BG', 'BGR', '100'], // Bulgaria + ['BH', 'BHR', '048'], // Bahrain + ['BI', 'BDI', '108'], // Burundi + ['BJ', 'BEN', '204'], // Benin + ['BL', 'BLM', '652'], // Saint Barthélemy + ['BM', 'BMU', '060'], // Bermuda + ['BN', 'BRN', '096'], // Brunei Darussalam + ['BO', 'BOL', '068'], // Bolivia, Plurinational State of + ['BQ', 'ATB', null], // British Antarctic Territory + ['BQ', 'BES', '535'], // Bonaire, Sint Eustatius and Saba + ['BR', 'BRA', '076'], // Brazil + ['BS', 'BHS', '044'], // Bahamas + ['BT', 'BTN', '064'], // Bhutan + ['BU', 'BUR', '104'], // Burma, Socialist Republic of the Union of + ['BV', 'BVT', '074'], // Bouvet Island + ['BW', 'BWA', '072'], // Botswana + ['BY', 'BLR', '112'], // Belarus + ['BY', 'BYS', '112'], // Byelorussian SSR Soviet Socialist Republic + ['BZ', 'BLZ', '084'], // Belize + ['CA', 'CAN', '124'], // Canada + ['CC', 'CCK', '166'], // Cocos (Keeling) Islands + ['CD', 'COD', '180'], // Congo, The Democratic Republic of the + ['CF', 'CAF', '140'], // Central African Republic + ['CG', 'COG', '178'], // Congo + ['CH', 'CHE', '756'], // Switzerland + ['CI', 'CIV', '384'], // Côte d'Ivoire + ['CK', 'COK', '184'], // Cook Islands + ['CL', 'CHL', '152'], // Chile + ['CM', 'CMR', '120'], // Cameroon + ['CN', 'CHN', '156'], // China + ['CO', 'COL', '170'], // Colombia + ['CR', 'CRI', '188'], // Costa Rica + ['CS', 'CSK', '200'], // Czechoslovakia, Czechoslovak Socialist Republic + ['CS', 'SCG', '891'], // Serbia and Montenegro + ['CT', 'CTE', '128'], // Canton and Enderbury Islands + ['CU', 'CUB', '192'], // Cuba + ['CV', 'CPV', '132'], // Cabo Verde + ['CW', 'CUW', '531'], // Curaçao + ['CX', 'CXR', '162'], // Christmas Island + ['CY', 'CYP', '196'], // Cyprus + ['CZ', 'CZE', '203'], // Czechia + ['DD', 'DDR', '278'], // German Democratic Republic + ['DE', 'DEU', '276'], // Germany + ['DJ', 'DJI', '262'], // Djibouti + ['DK', 'DNK', '208'], // Denmark + ['DM', 'DMA', '212'], // Dominica + ['DO', 'DOM', '214'], // Dominican Republic + ['DY', 'DHY', '204'], // Dahomey + ['DZ', 'DZA', '012'], // Algeria + ['EC', 'ECU', '218'], // Ecuador + ['EE', 'EST', '233'], // Estonia + ['EG', 'EGY', '818'], // Egypt + ['EH', 'ESH', '732'], // Western Sahara + ['ER', 'ERI', '232'], // Eritrea + ['ES', 'ESP', '724'], // Spain + ['ET', 'ETH', '231'], // Ethiopia + ['FI', 'FIN', '246'], // Finland + ['FJ', 'FJI', '242'], // Fiji + ['FK', 'FLK', '238'], // Falkland Islands (Malvinas) + ['FM', 'FSM', '583'], // Micronesia, Federated States of + ['FO', 'FRO', '234'], // Faroe Islands + ['FQ', 'ATF', null], // French Southern and Antarctic Territories + ['FR', 'FRA', '250'], // France + ['FX', 'FXX', '249'], // France, Metropolitan + ['GA', 'GAB', '266'], // Gabon + ['GB', 'GBR', '826'], // United Kingdom + ['GD', 'GRD', '308'], // Grenada + ['GE', 'GEL', '296'], // Gilbert and Ellice Islands + ['GE', 'GEO', '268'], // Georgia + ['GF', 'GUF', '254'], // French Guiana + ['GG', 'GGY', '831'], // Guernsey + ['GH', 'GHA', '288'], // Ghana + ['GI', 'GIB', '292'], // Gibraltar + ['GL', 'GRL', '304'], // Greenland + ['GM', 'GMB', '270'], // Gambia + ['GN', 'GIN', '324'], // Guinea + ['GP', 'GLP', '312'], // Guadeloupe + ['GQ', 'GNQ', '226'], // Equatorial Guinea + ['GR', 'GRC', '300'], // Greece + ['GS', 'SGS', '239'], // South Georgia and the South Sandwich Islands + ['GT', 'GTM', '320'], // Guatemala + ['GU', 'GUM', '316'], // Guam + ['GW', 'GNB', '624'], // Guinea-Bissau + ['GY', 'GUY', '328'], // Guyana + ['HK', 'HKG', '344'], // Hong Kong + ['HM', 'HMD', '334'], // Heard Island and McDonald Islands + ['HN', 'HND', '340'], // Honduras + ['HR', 'HRV', '191'], // Croatia + ['HT', 'HTI', '332'], // Haiti + ['HU', 'HUN', '348'], // Hungary + ['HV', 'HVO', '854'], // Upper Volta, Republic of + ['ID', 'IDN', '360'], // Indonesia + ['IE', 'IRL', '372'], // Ireland + ['IL', 'ISR', '376'], // Israel + ['IM', 'IMN', '833'], // Isle of Man + ['IN', 'IND', '356'], // India + ['IO', 'IOT', '086'], // British Indian Ocean Territory + ['IQ', 'IRQ', '368'], // Iraq + ['IR', 'IRN', '364'], // Iran, Islamic Republic of + ['IS', 'ISL', '352'], // Iceland + ['IT', 'ITA', '380'], // Italy + ['JE', 'JEY', '832'], // Jersey + ['JM', 'JAM', '388'], // Jamaica + ['JO', 'JOR', '400'], // Jordan + ['JP', 'JPN', '392'], // Japan + ['JT', 'JTN', '396'], // Johnston Island + ['KE', 'KEN', '404'], // Kenya + ['KG', 'KGZ', '417'], // Kyrgyzstan + ['KH', 'KHM', '116'], // Cambodia + ['KI', 'KIR', '296'], // Kiribati + ['KM', 'COM', '174'], // Comoros + ['KN', 'KNA', '659'], // Saint Kitts and Nevis + ['KP', 'PRK', '408'], // Korea, Democratic People's Republic of + ['KR', 'KOR', '410'], // Korea, Republic of + ['KW', 'KWT', '414'], // Kuwait + ['KY', 'CYM', '136'], // Cayman Islands + ['KZ', 'KAZ', '398'], // Kazakhstan + ['LA', 'LAO', '418'], // Lao People's Democratic Republic + ['LB', 'LBN', '422'], // Lebanon + ['LC', 'LCA', '662'], // Saint Lucia + ['LI', 'LIE', '438'], // Liechtenstein + ['LK', 'LKA', '144'], // Sri Lanka + ['LR', 'LBR', '430'], // Liberia + ['LS', 'LSO', '426'], // Lesotho + ['LT', 'LTU', '440'], // Lithuania + ['LU', 'LUX', '442'], // Luxembourg + ['LV', 'LVA', '428'], // Latvia + ['LY', 'LBY', '434'], // Libya + ['MA', 'MAR', '504'], // Morocco + ['MC', 'MCO', '492'], // Monaco + ['MD', 'MDA', '498'], // Moldova, Republic of + ['ME', 'MNE', '499'], // Montenegro + ['MF', 'MAF', '663'], // Saint Martin (French part) + ['MG', 'MDG', '450'], // Madagascar + ['MH', 'MHL', '584'], // Marshall Islands + ['MI', 'MID', '488'], // Midway Islands + ['MK', 'MKD', '807'], // North Macedonia + ['ML', 'MLI', '466'], // Mali + ['MM', 'MMR', '104'], // Myanmar + ['MN', 'MNG', '496'], // Mongolia + ['MO', 'MAC', '446'], // Macao + ['MP', 'MNP', '580'], // Northern Mariana Islands + ['MQ', 'MTQ', '474'], // Martinique + ['MR', 'MRT', '478'], // Mauritania + ['MS', 'MSR', '500'], // Montserrat + ['MT', 'MLT', '470'], // Malta + ['MU', 'MUS', '480'], // Mauritius + ['MV', 'MDV', '462'], // Maldives + ['MW', 'MWI', '454'], // Malawi + ['MX', 'MEX', '484'], // Mexico + ['MY', 'MYS', '458'], // Malaysia + ['MZ', 'MOZ', '508'], // Mozambique + ['NA', 'NAM', '516'], // Namibia + ['NC', 'NCL', '540'], // New Caledonia + ['NE', 'NER', '562'], // Niger + ['NF', 'NFK', '574'], // Norfolk Island + ['NG', 'NGA', '566'], // Nigeria + ['NH', 'NHB', '548'], // New Hebrides + ['NI', 'NIC', '558'], // Nicaragua + ['NL', 'NLD', '528'], // Netherlands + ['NO', 'NOR', '578'], // Norway + ['NP', 'NPL', '524'], // Nepal + ['NQ', 'ATN', '216'], // Dronning Maud Land + ['NR', 'NRU', '520'], // Nauru + ['NT', 'NTZ', '536'], // Neutral Zone + ['NU', 'NIU', '570'], // Niue + ['NZ', 'NZL', '554'], // New Zealand + ['OM', 'OMN', '512'], // Oman + ['PA', 'PAN', '591'], // Panama + ['PC', 'PCI', '582'], // Pacific Islands (trust territory) + ['PE', 'PER', '604'], // Peru + ['PF', 'PYF', '258'], // French Polynesia + ['PG', 'PNG', '598'], // Papua New Guinea + ['PH', 'PHL', '608'], // Philippines + ['PK', 'PAK', '586'], // Pakistan + ['PL', 'POL', '616'], // Poland + ['PM', 'SPM', '666'], // Saint Pierre and Miquelon + ['PN', 'PCN', '612'], // Pitcairn + ['PR', 'PRI', '630'], // Puerto Rico + ['PS', 'PSE', '275'], // Palestine, State of + ['PT', 'PRT', '620'], // Portugal + ['PU', 'PUS', '849'], // US Miscellaneous Pacific Islands + ['PW', 'PLW', '585'], // Palau + ['PY', 'PRY', '600'], // Paraguay + ['PZ', 'PCZ', null], // Panama Canal Zone + ['QA', 'QAT', '634'], // Qatar + ['RE', 'REU', '638'], // Réunion + ['RH', 'RHO', '716'], // Southern Rhodesia + ['RO', 'ROU', '642'], // Romania + ['RS', 'SRB', '688'], // Serbia + ['RU', 'RUS', '643'], // Russian Federation + ['RW', 'RWA', '646'], // Rwanda + ['SA', 'SAU', '682'], // Saudi Arabia + ['SB', 'SLB', '090'], // Solomon Islands + ['SC', 'SYC', '690'], // Seychelles + ['SD', 'SDN', '729'], // Sudan + ['SE', 'SWE', '752'], // Sweden + ['SG', 'SGP', '702'], // Singapore + ['SH', 'SHN', '654'], // Saint Helena, Ascension and Tristan da Cunha + ['SI', 'SVN', '705'], // Slovenia + ['SJ', 'SJM', '744'], // Svalbard and Jan Mayen + ['SK', 'SKM', null], // Sikkim + ['SK', 'SVK', '703'], // Slovakia + ['SL', 'SLE', '694'], // Sierra Leone + ['SM', 'SMR', '674'], // San Marino + ['SN', 'SEN', '686'], // Senegal + ['SO', 'SOM', '706'], // Somalia + ['SR', 'SUR', '740'], // Suriname + ['SS', 'SSD', '728'], // South Sudan + ['ST', 'STP', '678'], // Sao Tome and Principe + ['SU', 'SUN', '810'], // USSR, Union of Soviet Socialist Republics + ['SV', 'SLV', '222'], // El Salvador + ['SX', 'SXM', '534'], // Sint Maarten (Dutch part) + ['SY', 'SYR', '760'], // Syrian Arab Republic + ['SZ', 'SWZ', '748'], // Eswatini + ['TC', 'TCA', '796'], // Turks and Caicos Islands + ['TD', 'TCD', '148'], // Chad + ['TF', 'ATF', '260'], // French Southern Territories + ['TG', 'TGO', '768'], // Togo + ['TH', 'THA', '764'], // Thailand + ['TJ', 'TJK', '762'], // Tajikistan + ['TK', 'TKL', '772'], // Tokelau + ['TL', 'TLS', '626'], // Timor-Leste + ['TM', 'TKM', '795'], // Turkmenistan + ['TN', 'TUN', '788'], // Tunisia + ['TO', 'TON', '776'], // Tonga + ['TP', 'TMP', '626'], // East Timor + ['TR', 'TUR', '792'], // Türkiye + ['TT', 'TTO', '780'], // Trinidad and Tobago + ['TV', 'TUV', '798'], // Tuvalu + ['TW', 'TWN', '158'], // Taiwan, Province of China + ['TZ', 'TZA', '834'], // Tanzania, United Republic of + ['UA', 'UKR', '804'], // Ukraine + ['UG', 'UGA', '800'], // Uganda + ['UM', 'UMI', '581'], // United States Minor Outlying Islands + ['US', 'USA', '840'], // United States + ['UY', 'URY', '858'], // Uruguay + ['UZ', 'UZB', '860'], // Uzbekistan + ['VA', 'VAT', '336'], // Holy See (Vatican City State) + ['VC', 'VCT', '670'], // Saint Vincent and the Grenadines + ['VD', 'VDR', null], // Viet-Nam, Democratic Republic of + ['VE', 'VEN', '862'], // Venezuela, Bolivarian Republic of + ['VG', 'VGB', '092'], // Virgin Islands, British + ['VI', 'VIR', '850'], // Virgin Islands, U.S. + ['VN', 'VNM', '704'], // Viet Nam + ['VU', 'VUT', '548'], // Vanuatu + ['WF', 'WLF', '876'], // Wallis and Futuna + ['WK', 'WAK', '872'], // Wake Island + ['WS', 'WSM', '882'], // Samoa + ['YD', 'YMD', '720'], // Yemen, Democratic, People's Democratic Republic of + ['YE', 'YEM', '887'], // Yemen + ['YT', 'MYT', '175'], // Mayotte + ['YU', 'YUG', '891'], // Yugoslavia, Socialist Federal Republic of + ['ZA', 'ZAF', '710'], // South Africa + ['ZM', 'ZMB', '894'], // Zambia + ['ZR', 'ZAR', '180'], // Zaire, Republic of + ['ZW', 'ZWE', '716'], // Zimbabwe + // end of auto-generated code + ]; + + /** + * @var string + */ + private $set; + + /** + * Initializes the rule. + * + * @throws ComponentException If $set is not a valid set + */ + public function __construct(string $set = self::ALPHA2) + { + if (!isset(self::SET_INDEXES[$set])) { + throw new ComponentException( + sprintf( + '"%s" is not a valid set for ISO 3166-1 (Available: %s)', + $set, + implode(', ', array_keys(self::SET_INDEXES)) + ) + ); + } + + $this->set = $set; + } + + /** + * {@inheritDoc} + */ + protected function getDataSource($input = null): array + { + return array_column(self::COUNTRY_CODES, self::SET_INDEXES[$this->set]); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Cpf.php b/cacme/vendor/workerman/validation/library/Rules/Cpf.php new file mode 100644 index 0000000..62f7503 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Cpf.php @@ -0,0 +1,59 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function intval; +use function mb_strlen; +use function preg_match; +use function preg_replace; + +/** + * Validates whether the input is a CPF (Brazilian Natural Persons Register) number. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Jair Henrique + * @author Jayson Reis + * @author Jean Pimentel + * @author William Espindola + */ +final class Cpf extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + // Code ported from jsfromhell.com + $c = preg_replace('/\D/', '', $input); + + if (mb_strlen($c) != 11 || preg_match('/^' . $c[0] . '{11}$/', $c) || $c === '01234567890') { + return false; + } + + $n = 0; + for ($s = 10, $i = 0; $s >= 2; ++$i, --$s) { + $n += intval($c[$i]) * $s; + } + + if ($c[9] != (($n %= 11) < 2 ? 0 : 11 - $n)) { + return false; + } + + $n = 0; + for ($s = 11, $i = 0; $s >= 2; ++$i, --$s) { + $n += intval($c[$i]) * $s; + } + + $check = ($n %= 11) < 2 ? 0 : 11 - $n; + + return $c[10] == $check; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/CreditCard.php b/cacme/vendor/workerman/validation/library/Rules/CreditCard.php new file mode 100644 index 0000000..3008497 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/CreditCard.php @@ -0,0 +1,102 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_keys; +use function implode; +use function is_scalar; +use function preg_match; +use function preg_replace; +use function sprintf; + +/** + * Validates whether the input is a credit card number. + * + * @author Alexander Gorshkov + * @author Andy Snell + * @author Henrique Moody + * @author Jean Pimentel + * @author Nick Lombard + * @author William Espindola + * @author Rakshit Arora + */ +final class CreditCard extends AbstractRule +{ + public const ANY = 'Any'; + + public const AMERICAN_EXPRESS = 'American Express'; + + public const DINERS_CLUB = 'Diners Club'; + + public const DISCOVER = 'Discover'; + + public const JCB = 'JCB'; + + public const MASTERCARD = 'MasterCard'; + + public const VISA = 'Visa'; + + public const RUPAY = 'RuPay'; + + private const BRAND_REGEX_LIST = [ + self::ANY => '/^[0-9]+$/', + self::AMERICAN_EXPRESS => '/^3[47]\d{13}$/', + self::DINERS_CLUB => '/^3(?:0[0-5]|[68]\d)\d{11}$/', + self::DISCOVER => '/^6(?:011|5\d{2})\d{12}$/', + self::JCB => '/^(?:2131|1800|35\d{3})\d{11}$/', + self::MASTERCARD => '/(5[1-5]|2[2-7])\d{14}$/', + self::VISA => '/^4\d{12}(?:\d{3})?$/', + self::RUPAY => '/^6(?!011)(?:0[0-9]{14}|52[12][0-9]{12})$/', + ]; + + /** + * @var string + */ + private $brand; + + /** + * Initializes the rule. + * + * @throws ComponentException + */ + public function __construct(string $brand = self::ANY) + { + if (!isset(self::BRAND_REGEX_LIST[$brand])) { + throw new ComponentException( + sprintf( + '"%s" is not a valid credit card brand (Available: %s)', + $brand, + implode(', ', array_keys(self::BRAND_REGEX_LIST)) + ) + ); + } + + $this->brand = $brand; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $input = (string) preg_replace('/[ .-]/', '', (string) $input); + if (!(new Luhn())->validate($input)) { + return false; + } + + return preg_match(self::BRAND_REGEX_LIST[$this->brand], $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/CurrencyCode.php b/cacme/vendor/workerman/validation/library/Rules/CurrencyCode.php new file mode 100644 index 0000000..4c3ab89 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/CurrencyCode.php @@ -0,0 +1,212 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates currency codes in ISO 4217. + * + * @author Henrique Moody + * @author Justin Hook + * @author Tim Strijdhorst + * @author William Espindola + */ +final class CurrencyCode extends AbstractSearcher +{ + /** + * @see http://www.currency-iso.org/en/home/tables/table-a1.html + * + * {@inheritDoc} + */ + protected function getDataSource($input = null): array + { + return [ + 'AED', // UAE Dirham + 'AFN', // Afghani + 'ALL', // Lek + 'AMD', // Armenian Dram + 'ANG', // Netherlands Antillean Guilder + 'AOA', // Kwanza + 'ARS', // Argentine Peso + 'AUD', // Australian Dollar + 'AWG', // Aruban Florin + 'AZN', // Azerbaijan Manat + 'BAM', // Convertible Mark + 'BBD', // Barbados Dollar + 'BDT', // Taka + 'BGN', // Bulgarian Lev + 'BHD', // Bahraini Dinar + 'BIF', // Burundi Franc + 'BMD', // Bermudian Dollar + 'BND', // Brunei Dollar + 'BOB', // Boliviano + 'BOV', // Mvdol + 'BRL', // Brazilian Real + 'BSD', // Bahamian Dollar + 'BTN', // Ngultrum + 'BWP', // Pula + 'BYN', // Belarusian Ruble + 'BZD', // Belize Dollar + 'CAD', // Canadian Dollar + 'CDF', // Congolese Franc + 'CHE', // WIR Euro + 'CHF', // Swiss Franc + 'CHW', // WIR Franc + 'CLF', // Unidad de Fomento + 'CLP', // Chilean Peso + 'CNY', // Yuan Renminbi + 'COP', // Colombian Peso + 'COU', // Unidad de Valor Real + 'CRC', // Costa Rican Colon + 'CUC', // Peso Convertible + 'CUP', // Cuban Peso + 'CVE', // Cabo Verde Escudo + 'CZK', // Czech Koruna + 'DJF', // Djibouti Franc + 'DKK', // Danish Krone + 'DOP', // Dominican Peso + 'DZD', // Algerian Dinar + 'EGP', // Egyptian Pound + 'ERN', // Nakfa + 'ETB', // Ethiopian Birr + 'EUR', // Euro + 'FJD', // Fiji Dollar + 'FKP', // Falkland Islands Pound + 'GBP', // Pound Sterling + 'GEL', // Lari + 'GHS', // Ghana Cedi + 'GIP', // Gibraltar Pound + 'GMD', // Dalasi + 'GNF', // Guinean Franc + 'GTQ', // Quetzal + 'GYD', // Guyana Dollar + 'HKD', // Hong Kong Dollar + 'HNL', // Lempira + 'HTG', // Gourde + 'HUF', // Forint + 'IDR', // Rupiah + 'ILS', // New Israeli Sheqel + 'INR', // Indian Rupee + 'IQD', // Iraqi Dinar + 'IRR', // Iranian Rial + 'ISK', // Iceland Krona + 'JMD', // Jamaican Dollar + 'JOD', // Jordanian Dinar + 'JPY', // Yen + 'KES', // Kenyan Shilling + 'KGS', // Som + 'KHR', // Riel + 'KMF', // Comorian Franc + 'KPW', // North Korean Won + 'KRW', // Won + 'KWD', // Kuwaiti Dinar + 'KYD', // Cayman Islands Dollar + 'KZT', // Tenge + 'LAK', // Lao Kip + 'LBP', // Lebanese Pound + 'LKR', // Sri Lanka Rupee + 'LRD', // Liberian Dollar + 'LSL', // Loti + 'LYD', // Libyan Dinar + 'MAD', // Moroccan Dirham + 'MDL', // Moldovan Leu + 'MGA', // Malagasy Ariary + 'MKD', // Denar + 'MMK', // Kyat + 'MNT', // Tugrik + 'MOP', // Pataca + 'MRU', // Ouguiya + 'MUR', // Mauritius Rupee + 'MVR', // Rufiyaa + 'MWK', // Malawi Kwacha + 'MXN', // Mexican Peso + 'MXV', // Mexican Unidad de Inversion (UDI) + 'MYR', // Malaysian Ringgit + 'MZN', // Mozambique Metical + 'NAD', // Namibia Dollar + 'NGN', // Naira + 'NIO', // Cordoba Oro + 'NOK', // Norwegian Krone + 'NPR', // Nepalese Rupee + 'NZD', // New Zealand Dollar + 'OMR', // Rial Omani + 'PAB', // Balboa + 'PEN', // Sol + 'PGK', // Kina + 'PHP', // Philippine Peso + 'PKR', // Pakistan Rupee + 'PLN', // Zloty + 'PYG', // Guarani + 'QAR', // Qatari Rial + 'RON', // Romanian Leu + 'RSD', // Serbian Dinar + 'RUB', // Russian Ruble + 'RWF', // Rwanda Franc + 'SAR', // Saudi Riyal + 'SBD', // Solomon Islands Dollar + 'SCR', // Seychelles Rupee + 'SDG', // Sudanese Pound + 'SEK', // Swedish Krona + 'SGD', // Singapore Dollar + 'SHP', // Saint Helena Pound + 'SLE', // Leone + 'SLL', // Leone + 'SOS', // Somali Shilling + 'SRD', // Surinam Dollar + 'SSP', // South Sudanese Pound + 'STN', // Dobra + 'SVC', // El Salvador Colon + 'SYP', // Syrian Pound + 'SZL', // Lilangeni + 'THB', // Baht + 'TJS', // Somoni + 'TMT', // Turkmenistan New Manat + 'TND', // Tunisian Dinar + 'TOP', // Pa’anga + 'TRY', // Turkish Lira + 'TTD', // Trinidad and Tobago Dollar + 'TWD', // New Taiwan Dollar + 'TZS', // Tanzanian Shilling + 'UAH', // Hryvnia + 'UGX', // Uganda Shilling + 'USD', // US Dollar + 'USN', // US Dollar (Next day) + 'UYI', // Uruguay Peso en Unidades Indexadas (UI) + 'UYU', // Peso Uruguayo + 'UYW', // Unidad Previsional + 'UZS', // Uzbekistan Sum + 'VED', // Bolívar Soberano + 'VES', // Bolívar Soberano + 'VND', // Dong + 'VUV', // Vatu + 'WST', // Tala + 'XAF', // CFA Franc BEAC + 'XAG', // Silver + 'XAU', // Gold + 'XBA', // Bond Markets Unit European Composite Unit (EURCO) + 'XBB', // Bond Markets Unit European Monetary Unit (E.M.U.-6) + 'XBC', // Bond Markets Unit European Unit of Account 9 (E.U.A.-9) + 'XBD', // Bond Markets Unit European Unit of Account 17 (E.U.A.-17) + 'XCD', // East Caribbean Dollar + 'XDR', // SDR (Special Drawing Right) + 'XOF', // CFA Franc BCEAO + 'XPD', // Palladium + 'XPF', // CFP Franc + 'XPT', // Platinum + 'XSU', // Sucre + 'XTS', // Codes specifically reserved for testing purposes + 'XUA', // ADB Unit of Account + 'XXX', // The codes assigned for transactions where no currency is involved + 'YER', // Yemeni Rial + 'ZAR', // Rand + 'ZMW', // Zambian Kwacha + 'ZWL', // Zimbabwe Dollar + ]; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Date.php b/cacme/vendor/workerman/validation/library/Rules/Date.php new file mode 100644 index 0000000..d39a758 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Date.php @@ -0,0 +1,67 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Helpers\CanValidateDateTime; + +use function date; +use function is_scalar; +use function preg_match; +use function sprintf; +use function strtotime; + +/** + * Validates if input is a date. + * + * @author Bruno Luiz da Silva + * @author Henrique Moody + */ +final class Date extends AbstractRule +{ + use CanValidateDateTime; + + /** + * @var string + */ + private $format; + + /** + * @var string + */ + private $sample; + + /** + * Initializes the rule. + * + * @throws ComponentException + */ + public function __construct(string $format = 'Y-m-d') + { + if (!preg_match('/^[djSFmMnYy\W]+$/', $format)) { + throw new ComponentException(sprintf('"%s" is not a valid date format', $format)); + } + + $this->format = $format; + $this->sample = date($format, strtotime('2005-12-30')); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + return $this->isDateTime($this->format, (string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/DateTime.php b/cacme/vendor/workerman/validation/library/Rules/DateTime.php new file mode 100644 index 0000000..cc1e6d2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/DateTime.php @@ -0,0 +1,66 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use DateTimeInterface; +use Respect\Validation\Helpers\CanValidateDateTime; + +use function date; +use function is_scalar; +use function strtotime; + +/** + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class DateTime extends AbstractRule +{ + use CanValidateDateTime; + + /** + * @var string|null + */ + private $format; + + /** + * @var string + */ + private $sample; + + /** + * Initializes the rule. + */ + public function __construct(?string $format = null) + { + $this->format = $format; + $this->sample = date($format ?: 'c', strtotime('2005-12-30 01:02:03')); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof DateTimeInterface) { + return $this->format === null; + } + + if (!is_scalar($input)) { + return false; + } + + if ($this->format === null) { + return strtotime((string) $input) !== false; + } + + return $this->isDateTime($this->format, (string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Decimal.php b/cacme/vendor/workerman/validation/library/Rules/Decimal.php new file mode 100644 index 0000000..49161ea --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Decimal.php @@ -0,0 +1,71 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_numeric; +use function is_string; +use function number_format; +use function preg_replace; +use function var_export; + +/** + * Validates the decimal + * + * @author Henrique Moody + */ +final class Decimal extends AbstractRule +{ + /** + * @var int + */ + private $decimals; + + public function __construct(int $decimals) + { + $this->decimals = $decimals; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input)) { + return false; + } + + return $this->toFormattedString($input) === $this->toRawString($input); + } + + /** + * @param mixed $input + */ + private function toRawString($input): string + { + if (is_string($input)) { + return $input; + } + + return var_export($input, true); + } + + /** + * @param mixed $input + */ + private function toFormattedString($input): string + { + $formatted = number_format((float) $input, $this->decimals, '.', ''); + if (is_string($input)) { + return $formatted; + } + + return preg_replace('/^(\d+\.\d)0*$/', '$1', $formatted) ?: ''; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Digit.php b/cacme/vendor/workerman/validation/library/Rules/Digit.php new file mode 100644 index 0000000..acb0b7a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Digit.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_digit; + +/** + * Validates whether the input contains only digits. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Nick Lombard + */ +final class Digit extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_digit($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Directory.php b/cacme/vendor/workerman/validation/library/Rules/Directory.php new file mode 100644 index 0000000..70bd3d2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Directory.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Directory as NativeDirectory; +use SplFileInfo; + +use function is_dir; +use function is_scalar; + +/** + * Validates if the given path is a directory. + * + * @author Henrique Moody + * @author William Espindola + */ +final class Directory extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $input->isDir(); + } + + if ($input instanceof NativeDirectory) { + return true; + } + + if (!is_scalar($input)) { + return false; + } + + return is_dir((string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Domain.php b/cacme/vendor/workerman/validation/library/Rules/Domain.php new file mode 100644 index 0000000..a731916 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Domain.php @@ -0,0 +1,180 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\DomainException; +use Respect\Validation\Exceptions\NestedValidationException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Validatable; + +use function array_merge; +use function array_pop; +use function count; +use function explode; +use function iterator_to_array; +use function mb_substr_count; + +/** + * Validates whether the input is a valid domain name or not. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Mehmet Tolga Avcioglu + * @author Nick Lombard + * @author Róbert Nagy + */ +final class Domain extends AbstractRule +{ + /** + * @var Validatable + */ + private $genericRule; + + /** + * @var Validatable + */ + private $tldRule; + + /** + * @var Validatable + */ + private $partsRule; + + public function __construct(bool $tldCheck = true) + { + $this->genericRule = $this->createGenericRule(); + $this->tldRule = $this->createTldRule($tldCheck); + $this->partsRule = $this->createPartsRule(); + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $exceptions = []; + + $this->collectAssertException($exceptions, $this->genericRule, $input); + $this->throwExceptions($exceptions, $input); + + $parts = explode('.', (string) $input); + if (count($parts) >= 2) { + $this->collectAssertException($exceptions, $this->tldRule, array_pop($parts)); + } + + foreach ($parts as $part) { + $this->collectAssertException($exceptions, $this->partsRule, $part); + } + + $this->throwExceptions($exceptions, $input); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + try { + $this->assert($input); + } catch (ValidationException $exception) { + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + try { + $this->assert($input); + } catch (NestedValidationException $exception) { + /** @var ValidationException $childException */ + foreach ($exception as $childException) { + throw $childException; + } + + throw $exception; + } + } + + /** + * @param ValidationException[] $exceptions + * @param mixed $input + */ + private function collectAssertException(array &$exceptions, Validatable $validator, $input): void + { + try { + $validator->assert($input); + } catch (NestedValidationException $nestedValidationException) { + $exceptions = array_merge( + $exceptions, + iterator_to_array($nestedValidationException) + ); + } catch (ValidationException $validationException) { + $exceptions[] = $validationException; + } + } + + private function createGenericRule(): Validatable + { + return new AllOf( + new StringType(), + new NoWhitespace(), + new Contains('.'), + new Length(3) + ); + } + + private function createTldRule(bool $realTldCheck): Validatable + { + if ($realTldCheck) { + return new Tld(); + } + + return new AllOf( + new Not(new StartsWith('-')), + new NoWhitespace(), + new Length(2) + ); + } + + private function createPartsRule(): Validatable + { + return new AllOf( + new Alnum('-'), + new Not(new StartsWith('-')), + new AnyOf( + new Not(new Contains('--')), + new Callback(static function ($str) { + return mb_substr_count($str, '--') == 1; + }) + ), + new Not(new EndsWith('-')) + ); + } + + /** + * @param ValidationException[] $exceptions + * @param mixed $input + */ + private function throwExceptions(array $exceptions, $input): void + { + if (count($exceptions)) { + /** @var DomainException $domainException */ + $domainException = $this->reportError($input); + $domainException->addChildren($exceptions); + + throw $domainException; + } + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Each.php b/cacme/vendor/workerman/validation/library/Rules/Each.php new file mode 100644 index 0000000..2da5fe1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Each.php @@ -0,0 +1,96 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\EachException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Helpers\CanValidateIterable; +use Respect\Validation\Validatable; + +/** + * Validates whether each value in the input is valid according to another rule. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Nick Lombard + * @author William Espindola + */ +final class Each extends AbstractRule +{ + use CanValidateIterable; + + /** + * @var Validatable + */ + private $rule; + + /** + * Initializes the constructor. + */ + public function __construct(Validatable $rule) + { + $this->rule = $rule; + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if (!$this->isIterable($input)) { + throw $this->reportError($input); + } + + $exceptions = []; + foreach ($input as $value) { + try { + $this->rule->assert($value); + } catch (ValidationException $exception) { + $exceptions[] = $exception; + } + } + + if (!empty($exceptions)) { + /** @var EachException $eachException */ + $eachException = $this->reportError($input); + $eachException->addChildren($exceptions); + + throw $eachException; + } + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + if (!$this->isIterable($input)) { + throw $this->reportError($input); + } + + foreach ($input as $value) { + $this->rule->check($value); + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + try { + $this->check($input); + } catch (ValidationException $exception) { + return false; + } + + return true; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Email.php b/cacme/vendor/workerman/validation/library/Rules/Email.php new file mode 100644 index 0000000..f638cb3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Email.php @@ -0,0 +1,70 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Egulias\EmailValidator\EmailValidator; +use Egulias\EmailValidator\Validation\RFCValidation; + +use function class_exists; +use function filter_var; +use function is_string; + +use const FILTER_VALIDATE_EMAIL; + +/** + * Validates an email address. + * + * @author Andrey Kolyshkin + * @author Eduardo Gulias Davis + * @author Henrique Moody + * @author Paul Karikari + */ +final class Email extends AbstractRule +{ + /** + * @var EmailValidator|null + */ + private $validator; + + /** + * Initializes the rule assigning the EmailValidator instance. + * + * If the EmailValidator instance is not defined, tries to create one. + */ + public function __construct(?EmailValidator $validator = null) + { + $this->validator = $validator ?: $this->createEmailValidator(); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + if ($this->validator !== null) { + return $this->validator->isValid($input, new RFCValidation()); + } + + return (bool) filter_var($input, FILTER_VALIDATE_EMAIL); + } + + private function createEmailValidator(): ?EmailValidator + { + if (class_exists(EmailValidator::class)) { + return new EmailValidator(); + } + + return null; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/EndsWith.php b/cacme/vendor/workerman/validation/library/Rules/EndsWith.php new file mode 100644 index 0000000..790db18 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/EndsWith.php @@ -0,0 +1,82 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function end; +use function is_array; +use function mb_strlen; +use function mb_strripos; +use function mb_strrpos; + +/** + * Validates only if the value is at the end of the input. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Hugo Hamon + * @author William Espindola + */ +final class EndsWith extends AbstractRule +{ + /** + * @var mixed + */ + private $endValue; + + /** + * @var bool + */ + private $identical; + + /** + * @param mixed $endValue + */ + public function __construct($endValue, bool $identical = false) + { + $this->endValue = $endValue; + $this->identical = $identical; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->identical) { + return $this->validateIdentical($input); + } + + return $this->validateEquals($input); + } + + /** + * @param mixed $input + */ + private function validateEquals($input): bool + { + if (is_array($input)) { + return end($input) == $this->endValue; + } + + return mb_strripos($input, $this->endValue) === mb_strlen($input) - mb_strlen($this->endValue); + } + + /** + * @param mixed $input + */ + private function validateIdentical($input): bool + { + if (is_array($input)) { + return end($input) === $this->endValue; + } + + return mb_strrpos($input, $this->endValue) === mb_strlen($input) - mb_strlen($this->endValue); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Equals.php b/cacme/vendor/workerman/validation/library/Rules/Equals.php new file mode 100644 index 0000000..012984b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Equals.php @@ -0,0 +1,43 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates if the input is equal to some value. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Hugo Hamon + */ +final class Equals extends AbstractRule +{ + /** + * @var mixed + */ + private $compareTo; + + /** + * Initializes the rule. + * + * @param mixed $compareTo + */ + public function __construct($compareTo) + { + $this->compareTo = $compareTo; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $input == $this->compareTo; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Equivalent.php b/cacme/vendor/workerman/validation/library/Rules/Equivalent.php new file mode 100644 index 0000000..3945f1c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Equivalent.php @@ -0,0 +1,57 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function mb_strtoupper; + +/** + * Validates if the input is equivalent to some value. + * + * @author Henrique Moody + */ +final class Equivalent extends AbstractRule +{ + /** + * @var mixed + */ + private $compareTo; + + /** + * Initializes the rule. + * + * @param mixed $compareTo + */ + public function __construct($compareTo) + { + $this->compareTo = $compareTo; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_scalar($input)) { + return $this->isStringEquivalent((string) $input); + } + + return $input == $this->compareTo; + } + + private function isStringEquivalent(string $input): bool + { + if (!is_scalar($this->compareTo)) { + return false; + } + + return mb_strtoupper((string) $input) === mb_strtoupper((string) $this->compareTo); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Even.php b/cacme/vendor/workerman/validation/library/Rules/Even.php new file mode 100644 index 0000000..b21268e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Even.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function filter_var; + +use const FILTER_VALIDATE_INT; + +/** + * Validates whether the input is an even number or not. + * + * @author Henrique Moody + * @author Jean Pimentel + * @author Paul Karikari + */ +final class Even extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (filter_var($input, FILTER_VALIDATE_INT) === false) { + return false; + } + + return (int) $input % 2 === 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Executable.php b/cacme/vendor/workerman/validation/library/Rules/Executable.php new file mode 100644 index 0000000..a1f2ce2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Executable.php @@ -0,0 +1,40 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use SplFileInfo; + +use function is_executable; +use function is_scalar; + +/** + * Validates if a file is an executable. + * + * @author Henrique Moody + * @author William Espindola + */ +final class Executable extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $input->isExecutable(); + } + + if (!is_scalar($input)) { + return false; + } + + return is_executable((string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Exists.php b/cacme/vendor/workerman/validation/library/Rules/Exists.php new file mode 100644 index 0000000..c1bff93 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Exists.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use SplFileInfo; + +use function file_exists; +use function is_string; + +/** + * @author Henrique Moody + * @author William Espindola + */ +final class Exists extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + $input = $input->getPathname(); + } + + return is_string($input) && file_exists($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Extension.php b/cacme/vendor/workerman/validation/library/Rules/Extension.php new file mode 100644 index 0000000..ed2a9a4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Extension.php @@ -0,0 +1,55 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use SplFileInfo; + +use function is_string; +use function pathinfo; + +use const PATHINFO_EXTENSION; + +/** + * Validate file extensions. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class Extension extends AbstractRule +{ + /** + * @var string + */ + private $extension; + + /** + * Initializes the rule. + */ + public function __construct(string $extension) + { + $this->extension = $extension; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $this->extension === $input->getExtension(); + } + + if (!is_string($input)) { + return false; + } + + return $this->extension === pathinfo($input, PATHINFO_EXTENSION); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Factor.php b/cacme/vendor/workerman/validation/library/Rules/Factor.php new file mode 100644 index 0000000..170f99a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Factor.php @@ -0,0 +1,61 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function abs; +use function is_integer; +use function is_numeric; + +/** + * Validates if the input is a factor of the defined dividend. + * + * @author Danilo Correa + * @author David Meister + * @author Henrique Moody + */ +final class Factor extends AbstractRule +{ + /** + * @var int + */ + private $dividend; + + /** + * Initializes the rule. + */ + public function __construct(int $dividend) + { + $this->dividend = $dividend; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + // Every integer is a factor of zero, and zero is the only integer that + // has zero for a factor. + if ($this->dividend === 0) { + return true; + } + + // Factors must be integers that are not zero. + if (!is_numeric($input) || (int) $input != $input || $input == 0) { + return false; + } + + $input = (int) abs((int) $input); + $dividend = (int) abs($this->dividend); + + // The dividend divided by the input must be an integer if input is a + // factor of the dividend. + return is_integer($dividend / $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/FalseVal.php b/cacme/vendor/workerman/validation/library/Rules/FalseVal.php new file mode 100644 index 0000000..aba23d5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/FalseVal.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function filter_var; + +use const FILTER_NULL_ON_FAILURE; +use const FILTER_VALIDATE_BOOLEAN; + +/** + * Validates if a value is considered as false. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class FalseVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return filter_var($input, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) === false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Fibonacci.php b/cacme/vendor/workerman/validation/library/Rules/Fibonacci.php new file mode 100644 index 0000000..c48476d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Fibonacci.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_numeric; + +/** + * Validates whether the input follows the Fibonacci integer sequence. + * + * @author Danilo Correa + * @author Henrique Moody + * @author Samuel Heinzmann + */ +final class Fibonacci extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input)) { + return false; + } + + $sequence = [0, 1]; + $position = 1; + while ($input > $sequence[$position]) { + ++$position; + $sequence[$position] = $sequence[$position - 1] + $sequence[$position - 2]; + } + + return $sequence[$position] === (int) $input; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/File.php b/cacme/vendor/workerman/validation/library/Rules/File.php new file mode 100644 index 0000000..fcf8a7c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/File.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use SplFileInfo; + +use function is_file; +use function is_string; + +/** + * Validates whether file input is as a regular filename. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class File extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $input->isFile(); + } + + return is_string($input) && is_file($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/FilterVar.php b/cacme/vendor/workerman/validation/library/Rules/FilterVar.php new file mode 100644 index 0000000..23463e2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/FilterVar.php @@ -0,0 +1,70 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_key_exists; +use function filter_var; +use function is_array; +use function is_int; + +use const FILTER_VALIDATE_BOOLEAN; +use const FILTER_VALIDATE_DOMAIN; +use const FILTER_VALIDATE_EMAIL; +use const FILTER_VALIDATE_FLOAT; +use const FILTER_VALIDATE_INT; +use const FILTER_VALIDATE_IP; +use const FILTER_VALIDATE_REGEXP; +use const FILTER_VALIDATE_URL; + +/** + * Validates the input with the PHP's filter_var() function. + * + * @author Henrique Moody + */ +final class FilterVar extends AbstractEnvelope +{ + private const ALLOWED_FILTERS = [ + FILTER_VALIDATE_BOOLEAN => 'is_bool', + FILTER_VALIDATE_DOMAIN => 'is_string', + FILTER_VALIDATE_EMAIL => 'is_string', + FILTER_VALIDATE_FLOAT => 'is_float', + FILTER_VALIDATE_INT => 'is_int', + FILTER_VALIDATE_IP => 'is_string', + FILTER_VALIDATE_REGEXP => 'is_string', + FILTER_VALIDATE_URL => 'is_string', + ]; + + /** + * Initializes the rule. + * + * @param mixed $options + * + * @throws ComponentException + */ + public function __construct(int $filter, $options = []) + { + if (!array_key_exists($filter, self::ALLOWED_FILTERS)) { + throw new ComponentException('Cannot accept the given filter'); + } + + $arguments = [$filter]; + if (is_array($options) || is_int($options)) { + $arguments[] = $options; + } + + parent::__construct(new Callback(static function ($input) use ($filter, $arguments) { + return (self::ALLOWED_FILTERS[$filter])( + filter_var($input, ...$arguments) + ); + })); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Finite.php b/cacme/vendor/workerman/validation/library/Rules/Finite.php new file mode 100644 index 0000000..26f7754 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Finite.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_finite; +use function is_numeric; + +/** + * Validates if the input is a finite number. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class Finite extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_numeric($input) && is_finite((float) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/FloatType.php b/cacme/vendor/workerman/validation/library/Rules/FloatType.php new file mode 100644 index 0000000..70d4964 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/FloatType.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_float; + +/** + * Validates whether the type of the input is float. + * + * @author Henrique Moody + * @author Reginaldo Junior <76regi@gmail.com> + */ +final class FloatType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_float($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/FloatVal.php b/cacme/vendor/workerman/validation/library/Rules/FloatVal.php new file mode 100644 index 0000000..2b7c55b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/FloatVal.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function filter_var; +use function is_float; + +use const FILTER_VALIDATE_FLOAT; + +/** + * Validate whether the input value is float. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + * @author Jayson Reis + */ +final class FloatVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_float(filter_var($input, FILTER_VALIDATE_FLOAT)); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Graph.php b/cacme/vendor/workerman/validation/library/Rules/Graph.php new file mode 100644 index 0000000..ca04fcf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Graph.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_graph; + +/** + * Validates if all characters in the input are printable and actually creates visible output (no white space). + * + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + * @author Nick Lombard + */ +final class Graph extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_graph($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/GreaterThan.php b/cacme/vendor/workerman/validation/library/Rules/GreaterThan.php new file mode 100644 index 0000000..d05abd7 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/GreaterThan.php @@ -0,0 +1,26 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates whether the input is less than a value. + * + * @author Henrique Moody + */ +final class GreaterThan extends AbstractComparison +{ + /** + * {@inheritDoc} + */ + protected function compare($left, $right): bool + { + return $left > $right; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/HexRgbColor.php b/cacme/vendor/workerman/validation/library/Rules/HexRgbColor.php new file mode 100644 index 0000000..51af1bf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/HexRgbColor.php @@ -0,0 +1,24 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates weather the input is a hex RGB color or not. + * + * @author Davide Pastore + * @author Henrique Moody + */ +final class HexRgbColor extends AbstractEnvelope +{ + public function __construct() + { + parent::__construct(new Regex('/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i')); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Iban.php b/cacme/vendor/workerman/validation/library/Rules/Iban.php new file mode 100644 index 0000000..89484f4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Iban.php @@ -0,0 +1,149 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function bcmod; +use function is_string; +use function ord; +use function preg_match; +use function preg_replace_callback; +use function str_replace; +use function strlen; +use function strval; +use function substr; + +/** + * Validates whether the input is a valid IBAN (International Bank Account Number) or not. + * + * @author Mazen Touati + */ +final class Iban extends AbstractRule +{ + private const COUNTRIES_LENGTHS = [ + 'AL' => 28, + 'AD' => 24, + 'AT' => 20, + 'AZ' => 28, + 'BH' => 22, + 'BE' => 16, + 'BA' => 20, + 'BR' => 29, + 'BG' => 22, + 'CR' => 21, + 'HR' => 21, + 'CY' => 28, + 'CZ' => 24, + 'DK' => 18, + 'DO' => 28, + 'EE' => 20, + 'FO' => 18, + 'FI' => 18, + 'FR' => 27, + 'GE' => 22, + 'DE' => 22, + 'GI' => 23, + 'GR' => 27, + 'GL' => 18, + 'GT' => 28, + 'HU' => 28, + 'IS' => 26, + 'IE' => 22, + 'IL' => 23, + 'IT' => 27, + 'JO' => 30, + 'KZ' => 20, + 'KW' => 30, + 'LV' => 21, + 'LB' => 28, + 'LI' => 21, + 'LT' => 20, + 'LU' => 20, + 'MK' => 19, + 'MT' => 31, + 'MR' => 27, + 'MU' => 30, + 'MD' => 24, + 'MC' => 27, + 'ME' => 22, + 'NL' => 18, + 'NO' => 15, + 'PK' => 24, + 'PL' => 28, + 'PS' => 29, + 'PT' => 25, + 'QA' => 29, + 'XK' => 20, + 'RO' => 24, + 'LC' => 32, + 'SM' => 27, + 'ST' => 25, + 'SA' => 24, + 'RS' => 22, + 'SC' => 31, + 'SK' => 24, + 'SI' => 19, + 'ES' => 24, + 'SE' => 24, + 'CH' => 21, + 'TL' => 23, + 'TN' => 24, + 'TR' => 26, + 'UA' => 29, + 'AE' => 23, + 'GB' => 22, + 'VG' => 24, + ]; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + $iban = str_replace(' ', '', $input); + if (!preg_match('/[A-Z0-9]{15,34}/', $iban)) { + return false; + } + + $countryCode = substr($iban, 0, 2); + if (!$this->hasValidCountryLength($iban, $countryCode)) { + return false; + } + + $checkDigits = substr($iban, 2, 2); + $bban = substr($iban, 4); + $rearranged = $bban . $countryCode . $checkDigits; + + return bcmod($this->convertToIntegerAsString($rearranged), '97') === '1'; + } + + private function hasValidCountryLength(string $iban, string $countryCode): bool + { + if (!isset(self::COUNTRIES_LENGTHS[$countryCode])) { + return false; + } + + return strlen($iban) === self::COUNTRIES_LENGTHS[$countryCode]; + } + + private function convertToIntegerAsString(string $reArrangedIban): string + { + return (string) preg_replace_callback( + '/[A-Z]/', + static function (array $match): string { + return strval(ord($match[0]) - 55); + }, + $reArrangedIban + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Identical.php b/cacme/vendor/workerman/validation/library/Rules/Identical.php new file mode 100644 index 0000000..02ee01c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Identical.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates if the input is identical to some value. + * + * @author Henrique Moody + */ +final class Identical extends AbstractRule +{ + /** + * @var mixed + */ + private $compareTo; + + /** + * Initializes the rule. + * + * @param mixed $compareTo + */ + public function __construct($compareTo) + { + $this->compareTo = $compareTo; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $input === $this->compareTo; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Image.php b/cacme/vendor/workerman/validation/library/Rules/Image.php new file mode 100644 index 0000000..619d8c2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Image.php @@ -0,0 +1,62 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use finfo; +use SplFileInfo; + +use function is_file; +use function is_string; +use function mb_strpos; + +use const FILEINFO_MIME_TYPE; + +/** + * Validates if the file is a valid image by checking its MIME type. + * + * @author Danilo Benevides + * @author Guilherme Siani + * @author Henrique Moody + */ +final class Image extends AbstractRule +{ + /** + * @var finfo + */ + private $fileInfo; + + /** + * Initializes the rule. + */ + public function __construct(?finfo $fileInfo = null) + { + $this->fileInfo = $fileInfo ?: new finfo(FILEINFO_MIME_TYPE); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $this->validate($input->getPathname()); + } + + if (!is_string($input)) { + return false; + } + + if (!is_file($input)) { + return false; + } + + return mb_strpos((string) $this->fileInfo->file($input), 'image/') === 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Imei.php b/cacme/vendor/workerman/validation/library/Rules/Imei.php new file mode 100644 index 0000000..130e5c7 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Imei.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function mb_strlen; +use function preg_replace; + +/** + * Validates is the input is a valid IMEI. + * + * @author Alexander Gorshkov + * @author Danilo Benevides + * @author Diego Oliveira + * @author Henrique Moody + */ +final class Imei extends AbstractRule +{ + private const IMEI_SIZE = 15; + + /** + * @see https://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity + * + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $numbers = (string) preg_replace('/\D/', '', (string) $input); + if (mb_strlen($numbers) != self::IMEI_SIZE) { + return false; + } + + return (new Luhn())->validate($numbers); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/In.php b/cacme/vendor/workerman/validation/library/Rules/In.php new file mode 100644 index 0000000..f737448 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/In.php @@ -0,0 +1,90 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function in_array; +use function is_array; +use function mb_stripos; +use function mb_strpos; + +/** + * Validates if the input can be found in a defined array or string. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class In extends AbstractRule +{ + /** + * @var mixed[]|mixed + */ + private $haystack; + + /** + * @var bool + */ + private $compareIdentical; + + /** + * Initializes the rule with the haystack and optionally compareIdentical flag. + * + * @param mixed[]|mixed $haystack + */ + public function __construct($haystack, bool $compareIdentical = false) + { + $this->haystack = $haystack; + $this->compareIdentical = $compareIdentical; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->compareIdentical) { + return $this->validateIdentical($input); + } + + return $this->validateEquals($input); + } + + /** + * @param mixed $input + */ + private function validateEquals($input): bool + { + if (is_array($this->haystack)) { + return in_array($input, $this->haystack); + } + + if ($input === null || $input === '') { + return $input == $this->haystack; + } + + return mb_stripos($this->haystack, (string) $input) !== false; + } + + /** + * @param mixed $input + */ + private function validateIdentical($input): bool + { + if (is_array($this->haystack)) { + return in_array($input, $this->haystack, true); + } + + if ($input === null || $input === '') { + return $input === $this->haystack; + } + + return mb_strpos($this->haystack, (string) $input) !== false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Infinite.php b/cacme/vendor/workerman/validation/library/Rules/Infinite.php new file mode 100644 index 0000000..55c4706 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Infinite.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_infinite; +use function is_numeric; + +/** + * Validates if the input is an infinite number + * + * @author Danilo Benevides + * @author Henrique Moody + */ +final class Infinite extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_numeric($input) && is_infinite((float) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Instance.php b/cacme/vendor/workerman/validation/library/Rules/Instance.php new file mode 100644 index 0000000..d7a6744 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Instance.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates if the input is an instance of the given class or interface. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + */ +final class Instance extends AbstractRule +{ + /** + * @var string + */ + private $instanceName; + + /** + * Initializes the rule with the expected instance name. + */ + public function __construct(string $instanceName) + { + $this->instanceName = $instanceName; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $input instanceof $this->instanceName; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/IntType.php b/cacme/vendor/workerman/validation/library/Rules/IntType.php new file mode 100644 index 0000000..561dc43 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/IntType.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_int; + +/** + * Validates whether the type of the input is integer. + * + * @author Henrique Moody + */ +final class IntType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_int($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/IntVal.php b/cacme/vendor/workerman/validation/library/Rules/IntVal.php new file mode 100644 index 0000000..d147a44 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/IntVal.php @@ -0,0 +1,42 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_int; +use function is_string; +use function preg_match; + +/** + * Validates if the input is an integer. + * + * @author Adam Benson + * @author Alexandre Gomes Gaigalas + * @author Andrei Drulchenko + * @author Danilo Benevides + * @author Henrique Moody + */ +final class IntVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_int($input)) { + return true; + } + + if (!is_string($input)) { + return false; + } + + return preg_match('/^-?\d+$/', $input) === 1; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Ip.php b/cacme/vendor/workerman/validation/library/Rules/Ip.php new file mode 100644 index 0000000..a725533 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Ip.php @@ -0,0 +1,209 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function bccomp; +use function explode; +use function filter_var; +use function ip2long; +use function is_string; +use function long2ip; +use function mb_strpos; +use function mb_substr_count; +use function sprintf; +use function str_repeat; +use function str_replace; +use function strtr; + +use const FILTER_VALIDATE_IP; + +/** + * Validates whether the input is a valid IP address. + * + * This validator uses the native filter_var() PHP function. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + * @author Luís Otávio Cobucci Oblonczyk + */ +final class Ip extends AbstractRule +{ + /** + * @var string|null + */ + private $range; + + /** + * @var int|null + */ + private $options; + + /** + * @var string|null + */ + private $startAddress; + + /** + * @var string|null + */ + private $endAddress; + + /** + * @var string|null + */ + private $mask; + + /** + * Initializes the rule defining the range and some options for filter_var(). + * + * @throws ComponentException In case the range is invalid + */ + public function __construct(string $range = '*', ?int $options = null) + { + $this->parseRange($range); + $this->range = $this->createRange(); + $this->options = $options; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + if (!$this->verifyAddress($input)) { + return false; + } + + if ($this->mask) { + return $this->belongsToSubnet($input); + } + + if ($this->startAddress && $this->endAddress) { + return $this->verifyNetwork($input); + } + + return true; + } + + private function createRange(): ?string + { + if ($this->startAddress && $this->endAddress) { + return $this->startAddress . '-' . $this->endAddress; + } + + if ($this->startAddress && $this->mask) { + return $this->startAddress . '/' . long2ip((int) $this->mask); + } + + return null; + } + + private function parseRange(string $input): void + { + if ($input == '*' || $input == '*.*.*.*' || $input == '0.0.0.0-255.255.255.255') { + return; + } + + if (mb_strpos($input, '-') !== false) { + [$this->startAddress, $this->endAddress] = explode('-', $input); + + if ($this->startAddress !== null && !$this->verifyAddress($this->startAddress)) { + throw new ComponentException('Invalid network range'); + } + + if ($this->endAddress !== null && !$this->verifyAddress($this->endAddress)) { + throw new ComponentException('Invalid network range'); + } + + return; + } + + if (mb_strpos($input, '*') !== false) { + $this->parseRangeUsingWildcards($input); + + return; + } + + if (mb_strpos($input, '/') !== false) { + $this->parseRangeUsingCidr($input); + + return; + } + + throw new ComponentException('Invalid network range'); + } + + private function fillAddress(string $address, string $fill = '*'): string + { + return $address . str_repeat('.' . $fill, 3 - mb_substr_count($address, '.')); + } + + private function parseRangeUsingWildcards(string $input): void + { + $address = $this->fillAddress($input); + + $this->startAddress = strtr($address, '*', '0'); + $this->endAddress = str_replace('*', '255', $address); + } + + private function parseRangeUsingCidr(string $input): void + { + $parts = explode('/', $input); + + $this->startAddress = $this->fillAddress($parts[0], '0'); + $isAddressMask = mb_strpos($parts[1], '.') !== false; + + if ($isAddressMask && $this->verifyAddress($parts[1])) { + $this->mask = sprintf('%032b', ip2long($parts[1])); + + return; + } + + if ($isAddressMask || $parts[1] < 8 || $parts[1] > 30) { + throw new ComponentException('Invalid network mask'); + } + + $this->mask = sprintf('%032b', ip2long((string) long2ip(~(2 ** (32 - (int) $parts[1]) - 1)))); + } + + private function verifyAddress(string $address): bool + { + return filter_var($address, FILTER_VALIDATE_IP, ['flags' => $this->options]) !== false; + } + + private function verifyNetwork(string $input): bool + { + $input = sprintf('%u', ip2long($input)); + + return $this->startAddress !== null + && $this->endAddress !== null + && bccomp($input, sprintf('%u', ip2long($this->startAddress))) >= 0 + && bccomp($input, sprintf('%u', ip2long($this->endAddress))) <= 0; + } + + private function belongsToSubnet(string $input): bool + { + if ($this->mask === null || $this->startAddress === null) { + return false; + } + + $min = sprintf('%032b', ip2long($this->startAddress)); + $input = sprintf('%032b', ip2long($input)); + + return ($input & $this->mask) === ($min & $this->mask); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Isbn.php b/cacme/vendor/workerman/validation/library/Rules/Isbn.php new file mode 100644 index 0000000..4c0dd14 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Isbn.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function implode; +use function is_scalar; +use function preg_match; +use function sprintf; + +/** + * Validates whether the input is a valid ISBN (International Standard Book Number) or not. + * + * @author Henrique Moody + * @author Moritz Fromm + */ +final class Isbn extends AbstractRule +{ + /** + * @see https://howtodoinjava.com/regex/java-regex-validate-international-standard-book-number-isbns + */ + private const PIECES = [ + '^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})', + '[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)', + '(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$', + ]; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + return preg_match(sprintf('/%s/', implode(self::PIECES)), (string) $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/IterableType.php b/cacme/vendor/workerman/validation/library/Rules/IterableType.php new file mode 100644 index 0000000..92bd300 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/IterableType.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CanValidateIterable; + +/** + * Validates whether the pseudo-type of the input is iterable or not. + * + * @author Henrique Moody + */ +final class IterableType extends AbstractRule +{ + use CanValidateIterable; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $this->isIterable($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Json.php b/cacme/vendor/workerman/validation/library/Rules/Json.php new file mode 100644 index 0000000..5ce14fc --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Json.php @@ -0,0 +1,44 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function function_exists; +use function is_string; +use function json_decode; +use function json_last_error; + +use const JSON_ERROR_NONE; + +/** + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class Json extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input) || $input === '') { + return false; + } + + if (function_exists('json_validate')) { + return json_validate($input); + } + + json_decode($input); + + return json_last_error() === JSON_ERROR_NONE; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Key.php b/cacme/vendor/workerman/validation/library/Rules/Key.php new file mode 100644 index 0000000..fa84291 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Key.php @@ -0,0 +1,53 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Validatable; + +use function array_key_exists; +use function is_array; +use function is_scalar; + +/** + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class Key extends AbstractRelated +{ + /** + * @param mixed $reference + */ + public function __construct($reference, ?Validatable $rule = null, bool $mandatory = true) + { + if (!is_scalar($reference) || $reference === '') { + throw new ComponentException('Invalid array key name'); + } + + parent::__construct($reference, $rule, $mandatory); + } + + /** + * {@inheritDoc} + */ + public function getReferenceValue($input) + { + return $input[$this->getReference()]; + } + + /** + * {@inheritDoc} + */ + public function hasReference($input): bool + { + return is_array($input) && array_key_exists($this->getReference(), $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/KeyNested.php b/cacme/vendor/workerman/validation/library/Rules/KeyNested.php new file mode 100644 index 0000000..582e94d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/KeyNested.php @@ -0,0 +1,146 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use ArrayAccess; +use Respect\Validation\Exceptions\ComponentException; + +use function array_key_exists; +use function array_shift; +use function explode; +use function is_array; +use function is_null; +use function is_object; +use function is_scalar; +use function property_exists; +use function rtrim; +use function sprintf; + +/** + * @author Alexandre Gomes Gaigalas + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Ivan Zinovyev + */ +final class KeyNested extends AbstractRelated +{ + /** + * {@inheritDoc} + */ + public function hasReference($input): bool + { + try { + $this->getReferenceValue($input); + } catch (ComponentException $cex) { + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + public function getReferenceValue($input) + { + if (is_scalar($input)) { + $message = sprintf('Cannot select the %s in the given data', $this->getReference()); + throw new ComponentException($message); + } + + $keys = $this->getReferencePieces(); + $value = $input; + while (!is_null($key = array_shift($keys))) { + $value = $this->getValue($value, $key); + } + + return $value; + } + + /** + * @return string[] + */ + private function getReferencePieces(): array + { + return explode('.', rtrim((string) $this->getReference(), '.')); + } + + /** + * @param mixed[] $array + * @param mixed $key + * + * @return mixed + */ + private function getValueFromArray(array $array, $key) + { + if (!array_key_exists($key, $array)) { + $message = sprintf('Cannot select the key %s from the given array', $this->getReference()); + throw new ComponentException($message); + } + + return $array[$key]; + } + + /** + * @param ArrayAccess $array + * @param mixed $key + * + * @return mixed + */ + private function getValueFromArrayAccess(ArrayAccess $array, $key) + { + if (!$array->offsetExists($key)) { + $message = sprintf('Cannot select the key %s from the given array', $this->getReference()); + throw new ComponentException($message); + } + + return $array->offsetGet($key); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint + * + * + * @return mixed + */ + private function getValueFromObject(object $object, string $property) + { + if (empty($property) || !property_exists($object, $property)) { + $message = sprintf('Cannot select the property %s from the given object', $this->getReference()); + throw new ComponentException($message); + } + + return $object->{$property}; + } + + /** + * @param mixed $value + * @param mixed $key + * + * @return mixed + */ + private function getValue($value, $key) + { + if (is_array($value)) { + return $this->getValueFromArray($value, $key); + } + + if ($value instanceof ArrayAccess) { + return $this->getValueFromArrayAccess($value, $key); + } + + if (is_object($value)) { + return $this->getValueFromObject($value, $key); + } + + $message = sprintf('Cannot select the property %s from the given data', $this->getReference()); + throw new ComponentException($message); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/KeySet.php b/cacme/vendor/workerman/validation/library/Rules/KeySet.php new file mode 100644 index 0000000..accc5ed --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/KeySet.php @@ -0,0 +1,142 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\NonNegatable; +use Respect\Validation\Validatable; + +use function array_key_exists; +use function array_map; +use function count; +use function current; +use function is_array; + +/** + * Validates a keys in a defined structure. + * + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class KeySet extends AbstractWrapper implements NonNegatable +{ + /** + * @var mixed[] + */ + private $keys; + + /** + * @var mixed[] + */ + private $extraKeys = []; + + /** + * @var Key[] + */ + private $keyRules; + + /** + * Initializes the rule. + * + * phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.UselessAnnotation + * @param Validatable ...$validatables + */ + public function __construct(Validatable ...$validatables) + { + $this->keyRules = array_map([$this, 'getKeyRule'], $validatables); + $this->keys = array_map([$this, 'getKeyReference'], $this->keyRules); + + parent::__construct(new AllOf(...$this->keyRules)); + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if (!$this->hasValidStructure($input)) { + throw $this->reportError($input); + } + + parent::assert($input); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + if (!$this->hasValidStructure($input)) { + throw $this->reportError($input); + } + + parent::check($input); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!$this->hasValidStructure($input)) { + return false; + } + + return parent::validate($input); + } + + /** + * @throws ComponentException + */ + private function getKeyRule(Validatable $validatable): Key + { + if ($validatable instanceof Key) { + return $validatable; + } + + if (!$validatable instanceof AllOf || count($validatable->getRules()) !== 1) { + throw new ComponentException('KeySet rule accepts only Key rules'); + } + + return $this->getKeyRule(current($validatable->getRules())); + } + + /** + * @return mixed + */ + private function getKeyReference(Key $rule) + { + return $rule->getReference(); + } + + /** + * @param mixed $input + */ + private function hasValidStructure($input): bool + { + if (!is_array($input)) { + return false; + } + + foreach ($this->keyRules as $keyRule) { + if (!array_key_exists($keyRule->getReference(), $input) && $keyRule->isMandatory()) { + return false; + } + + unset($input[$keyRule->getReference()]); + } + + foreach ($input as $extraKey => &$ignoreValue) { + $this->extraKeys[] = $extraKey; + } + + return count($input) == 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/KeyValue.php b/cacme/vendor/workerman/validation/library/Rules/KeyValue.php new file mode 100644 index 0000000..dee38e3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/KeyValue.php @@ -0,0 +1,144 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Factory; +use Respect\Validation\Validatable; + +use function array_keys; +use function in_array; + +/** + * @author Henrique Moody + */ +final class KeyValue extends AbstractRule +{ + /** + * @var int|string + */ + private $comparedKey; + + /** + * @var string + */ + private $ruleName; + + /** + * @var int|string + */ + private $baseKey; + + /** + * @param int|string $comparedKey + * @param int|string $baseKey + */ + public function __construct($comparedKey, string $ruleName, $baseKey) + { + $this->comparedKey = $comparedKey; + $this->ruleName = $ruleName; + $this->baseKey = $baseKey; + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $rule = $this->getRule($input); + + try { + $rule->assert($input[$this->comparedKey]); + } catch (ValidationException $exception) { + throw $this->overwriteExceptionParams($exception); + } + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + $rule = $this->getRule($input); + + try { + $rule->check($input[$this->comparedKey]); + } catch (ValidationException $exception) { + throw $this->overwriteExceptionParams($exception); + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + try { + $rule = $this->getRule($input); + } catch (ValidationException $e) { + return false; + } + + return $rule->validate($input[$this->comparedKey]); + } + + /** + * {@inheritDoc} + */ + public function reportError($input, array $extraParams = []): ValidationException + { + try { + return $this->overwriteExceptionParams($this->getRule($input)->reportError($input)); + } catch (ValidationException $exception) { + return $this->overwriteExceptionParams($exception); + } + } + + /** + * @param mixed $input + */ + private function getRule($input): Validatable + { + if (!isset($input[$this->comparedKey])) { + throw parent::reportError($this->comparedKey); + } + + if (!isset($input[$this->baseKey])) { + throw parent::reportError($this->baseKey); + } + + try { + $rule = Factory::getDefaultInstance()->rule($this->ruleName, [$input[$this->baseKey]]); + $rule->setName((string) $this->comparedKey); + } catch (ComponentException $exception) { + throw parent::reportError($input, ['component' => true]); + } + + return $rule; + } + + private function overwriteExceptionParams(ValidationException $exception): ValidationException + { + $params = []; + foreach (array_keys($exception->getParams()) as $key) { + if (in_array($key, ['template', 'translator'])) { + continue; + } + + $params[$key] = $this->baseKey; + } + $params['name'] = $this->comparedKey; + + $exception->updateParams($params); + + return $exception; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/LanguageCode.php b/cacme/vendor/workerman/validation/library/Rules/LanguageCode.php new file mode 100644 index 0000000..ffcec15 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/LanguageCode.php @@ -0,0 +1,549 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_column; +use function array_filter; +use function array_search; +use function sprintf; + +/** + * Validates whether the input is language code based on ISO 639. + * + * @author Danilo Benevides + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class LanguageCode extends AbstractEnvelope +{ + public const ALPHA2 = 'alpha-2'; + public const ALPHA3 = 'alpha-3'; + + public const AVAILABLE_SETS = [self::ALPHA2, self::ALPHA3]; + + /** + * @see http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt + */ + public const LANGUAGE_CODES = [ + // phpcs:disable Squiz.PHP.CommentedOutCode.Found + ['aa', 'aar'], // Afar + ['ab', 'abk'], // Abkhazian + ['', 'ace'], // Achinese + ['', 'ach'], // Acoli + ['', 'ada'], // Adangme + ['', 'ady'], // Adyghe; Adygei + ['', 'afa'], // Afro-Asiatic languages + ['', 'afh'], // Afrihili + ['af', 'afr'], // Afrikaans + ['', 'ain'], // Ainu + ['ak', 'aka'], // Akan + ['', 'akk'], // Akkadian + ['sq', 'alb'], // Albanian + ['', 'ale'], // Aleut + ['', 'alg'], // Algonquian languages + ['', 'alt'], // Southern Altai + ['am', 'amh'], // Amharic + ['', 'ang'], // English, Old (ca.450-1100) + ['', 'anp'], // Angika + ['', 'apa'], // Apache languages + ['ar', 'ara'], // Arabic + ['', 'arc'], // Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE) + ['an', 'arg'], // Aragonese + ['hy', 'arm'], // Armenian + ['', 'arn'], // Mapudungun; Mapuche + ['', 'arp'], // Arapaho + ['', 'art'], // Artificial languages + ['', 'arw'], // Arawak + ['as', 'asm'], // Assamese + ['', 'ast'], // Asturian; Bable; Leonese; Asturleonese + ['', 'ath'], // Athapascan languages + ['', 'aus'], // Australian languages + ['av', 'ava'], // Avaric + ['ae', 'ave'], // Avestan + ['', 'awa'], // Awadhi + ['ay', 'aym'], // Aymara + ['az', 'aze'], // Azerbaijani + ['', 'bad'], // Banda languages + ['', 'bai'], // Bamileke languages + ['ba', 'bak'], // Bashkir + ['', 'bal'], // Baluchi + ['bm', 'bam'], // Bambara + ['', 'ban'], // Balinese + ['eu', 'baq'], // Basque + ['', 'bas'], // Basa + ['', 'bat'], // Baltic languages + ['', 'bej'], // Beja; Bedawiyet + ['be', 'bel'], // Belarusian + ['', 'bem'], // Bemba + ['bn', 'ben'], // Bengali + ['', 'ber'], // Berber languages + ['', 'bho'], // Bhojpuri + ['bh', 'bih'], // Bihari languages + ['', 'bik'], // Bikol + ['', 'bin'], // Bini; Edo + ['bi', 'bis'], // Bislama + ['', 'bla'], // Siksika + ['', 'bnt'], // Bantu languages + ['bs', 'bos'], // Bosnian + ['', 'bra'], // Braj + ['br', 'bre'], // Breton + ['', 'btk'], // Batak languages + ['', 'bua'], // Buriat + ['', 'bug'], // Buginese + ['bg', 'bul'], // Bulgarian + ['my', 'bur'], // Burmese + ['', 'byn'], // Blin; Bilin + ['', 'cad'], // Caddo + ['', 'cai'], // Central American Indian languages + ['', 'car'], // Galibi Carib + ['ca', 'cat'], // Catalan; Valencian + ['', 'cau'], // Caucasian languages + ['', 'ceb'], // Cebuano + ['', 'cel'], // Celtic languages + ['ch', 'cha'], // Chamorro + ['', 'chb'], // Chibcha + ['ce', 'che'], // Chechen + ['', 'chg'], // Chagatai + ['zh', 'chi'], // Chinese + ['', 'chk'], // Chuukese + ['', 'chm'], // Mari + ['', 'chn'], // Chinook jargon + ['', 'cho'], // Choctaw + ['', 'chp'], // Chipewyan; Dene Suline + ['', 'chr'], // Cherokee + ['cu', 'chu'], // Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic + ['cv', 'chv'], // Chuvash + ['', 'chy'], // Cheyenne + ['', 'cmc'], // Chamic languages + ['', 'cnr'], // Montenegrin + ['', 'cop'], // Coptic + ['kw', 'cor'], // Cornish + ['co', 'cos'], // Corsican + ['', 'cpe'], // Creoles and pidgins, English based + ['', 'cpf'], // Creoles and pidgins, French-based + ['', 'cpp'], // Creoles and pidgins, Portuguese-based + ['cr', 'cre'], // Cree + ['', 'crh'], // Crimean Tatar; Crimean Turkish + ['', 'crp'], // Creoles and pidgins + ['', 'csb'], // Kashubian + ['', 'cus'], // Cushitic languages + ['cs', 'cze'], // Czech + ['', 'dak'], // Dakota + ['da', 'dan'], // Danish + ['', 'dar'], // Dargwa + ['', 'day'], // Land Dayak languages + ['', 'del'], // Delaware + ['', 'den'], // Slave (Athapascan) + ['', 'dgr'], // Dogrib + ['', 'din'], // Dinka + ['dv', 'div'], // Divehi; Dhivehi; Maldivian + ['', 'doi'], // Dogri + ['', 'dra'], // Dravidian languages + ['', 'dsb'], // Lower Sorbian + ['', 'dua'], // Duala + ['', 'dum'], // Dutch, Middle (ca.1050-1350) + ['nl', 'dut'], // Dutch; Flemish + ['', 'dyu'], // Dyula + ['dz', 'dzo'], // Dzongkha + ['', 'efi'], // Efik + ['', 'egy'], // Egyptian (Ancient) + ['', 'eka'], // Ekajuk + ['', 'elx'], // Elamite + ['en', 'eng'], // English + ['', 'enm'], // English, Middle (1100-1500) + ['eo', 'epo'], // Esperanto + ['et', 'est'], // Estonian + ['ee', 'ewe'], // Ewe + ['', 'ewo'], // Ewondo + ['', 'fan'], // Fang + ['fo', 'fao'], // Faroese + ['', 'fat'], // Fanti + ['fj', 'fij'], // Fijian + ['', 'fil'], // Filipino; Pilipino + ['fi', 'fin'], // Finnish + ['', 'fiu'], // Finno-Ugrian languages + ['', 'fon'], // Fon + ['fr', 'fre'], // French + ['', 'frm'], // French, Middle (ca.1400-1600) + ['', 'fro'], // French, Old (842-ca.1400) + ['', 'frr'], // Northern Frisian + ['', 'frs'], // Eastern Frisian + ['fy', 'fry'], // Western Frisian + ['ff', 'ful'], // Fulah + ['', 'fur'], // Friulian + ['', 'gaa'], // Ga + ['', 'gay'], // Gayo + ['', 'gba'], // Gbaya + ['', 'gem'], // Germanic languages + ['ka', 'geo'], // Georgian + ['de', 'ger'], // German + ['', 'gez'], // Geez + ['', 'gil'], // Gilbertese + ['gd', 'gla'], // Gaelic; Scottish Gaelic + ['ga', 'gle'], // Irish + ['gl', 'glg'], // Galician + ['gv', 'glv'], // Manx + ['', 'gmh'], // German, Middle High (ca.1050-1500) + ['', 'goh'], // German, Old High (ca.750-1050) + ['', 'gon'], // Gondi + ['', 'gor'], // Gorontalo + ['', 'got'], // Gothic + ['', 'grb'], // Grebo + ['', 'grc'], // Greek, Ancient (to 1453) + ['el', 'gre'], // Greek, Modern (1453-) + ['gn', 'grn'], // Guarani + ['', 'gsw'], // Swiss German; Alemannic; Alsatian + ['gu', 'guj'], // Gujarati + ['', 'gwi'], // Gwich'in + ['', 'hai'], // Haida + ['ht', 'hat'], // Haitian; Haitian Creole + ['ha', 'hau'], // Hausa + ['', 'haw'], // Hawaiian + ['he', 'heb'], // Hebrew + ['hz', 'her'], // Herero + ['', 'hil'], // Hiligaynon + ['', 'him'], // Himachali languages; Western Pahari languages + ['hi', 'hin'], // Hindi + ['', 'hit'], // Hittite + ['', 'hmn'], // Hmong; Mong + ['ho', 'hmo'], // Hiri Motu + ['hr', 'hrv'], // Croatian + ['', 'hsb'], // Upper Sorbian + ['hu', 'hun'], // Hungarian + ['', 'hup'], // Hupa + ['', 'iba'], // Iban + ['ig', 'ibo'], // Igbo + ['is', 'ice'], // Icelandic + ['io', 'ido'], // Ido + ['ii', 'iii'], // Sichuan Yi; Nuosu + ['', 'ijo'], // Ijo languages + ['iu', 'iku'], // Inuktitut + ['ie', 'ile'], // Interlingue; Occidental + ['', 'ilo'], // Iloko + ['ia', 'ina'], // Interlingua (International Auxiliary Language Association) + ['', 'inc'], // Indic languages + ['id', 'ind'], // Indonesian + ['', 'ine'], // Indo-European languages + ['', 'inh'], // Ingush + ['ik', 'ipk'], // Inupiaq + ['', 'ira'], // Iranian languages + ['', 'iro'], // Iroquoian languages + ['it', 'ita'], // Italian + ['jv', 'jav'], // Javanese + ['', 'jbo'], // Lojban + ['ja', 'jpn'], // Japanese + ['', 'jpr'], // Judeo-Persian + ['', 'jrb'], // Judeo-Arabic + ['', 'kaa'], // Kara-Kalpak + ['', 'kab'], // Kabyle + ['', 'kac'], // Kachin; Jingpho + ['kl', 'kal'], // Kalaallisut; Greenlandic + ['', 'kam'], // Kamba + ['kn', 'kan'], // Kannada + ['', 'kar'], // Karen languages + ['ks', 'kas'], // Kashmiri + ['kr', 'kau'], // Kanuri + ['', 'kaw'], // Kawi + ['kk', 'kaz'], // Kazakh + ['', 'kbd'], // Kabardian + ['', 'kha'], // Khasi + ['', 'khi'], // Khoisan languages + ['km', 'khm'], // Central Khmer + ['', 'kho'], // Khotanese; Sakan + ['ki', 'kik'], // Kikuyu; Gikuyu + ['rw', 'kin'], // Kinyarwanda + ['ky', 'kir'], // Kirghiz; Kyrgyz + ['', 'kmb'], // Kimbundu + ['', 'kok'], // Konkani + ['kv', 'kom'], // Komi + ['kg', 'kon'], // Kongo + ['ko', 'kor'], // Korean + ['', 'kos'], // Kosraean + ['', 'kpe'], // Kpelle + ['', 'krc'], // Karachay-Balkar + ['', 'krl'], // Karelian + ['', 'kro'], // Kru languages + ['', 'kru'], // Kurukh + ['kj', 'kua'], // Kuanyama; Kwanyama + ['', 'kum'], // Kumyk + ['ku', 'kur'], // Kurdish + ['', 'kut'], // Kutenai + ['', 'lad'], // Ladino + ['', 'lah'], // Lahnda + ['', 'lam'], // Lamba + ['lo', 'lao'], // Lao + ['la', 'lat'], // Latin + ['lv', 'lav'], // Latvian + ['', 'lez'], // Lezghian + ['li', 'lim'], // Limburgan; Limburger; Limburgish + ['ln', 'lin'], // Lingala + ['lt', 'lit'], // Lithuanian + ['', 'lol'], // Mongo + ['', 'loz'], // Lozi + ['lb', 'ltz'], // Luxembourgish; Letzeburgesch + ['', 'lua'], // Luba-Lulua + ['lu', 'lub'], // Luba-Katanga + ['lg', 'lug'], // Ganda + ['', 'lui'], // Luiseno + ['', 'lun'], // Lunda + ['', 'luo'], // Luo (Kenya and Tanzania) + ['', 'lus'], // Lushai + ['mk', 'mac'], // Macedonian + ['', 'mad'], // Madurese + ['', 'mag'], // Magahi + ['mh', 'mah'], // Marshallese + ['', 'mai'], // Maithili + ['', 'mak'], // Makasar + ['ml', 'mal'], // Malayalam + ['', 'man'], // Mandingo + ['mi', 'mao'], // Maori + ['', 'map'], // Austronesian languages + ['mr', 'mar'], // Marathi + ['', 'mas'], // Masai + ['ms', 'may'], // Malay + ['', 'mdf'], // Moksha + ['', 'mdr'], // Mandar + ['', 'men'], // Mende + ['', 'mga'], // Irish, Middle (900-1200) + ['', 'mic'], // Mi'kmaq; Micmac + ['', 'min'], // Minangkabau + ['', 'mis'], // Uncoded languages + ['', 'mkh'], // Mon-Khmer languages + ['mg', 'mlg'], // Malagasy + ['mt', 'mlt'], // Maltese + ['', 'mnc'], // Manchu + ['', 'mni'], // Manipuri + ['', 'mno'], // Manobo languages + ['', 'moh'], // Mohawk + ['mn', 'mon'], // Mongolian + ['', 'mos'], // Mossi + ['', 'mul'], // Multiple languages + ['', 'mun'], // Munda languages + ['', 'mus'], // Creek + ['', 'mwl'], // Mirandese + ['', 'mwr'], // Marwari + ['', 'myn'], // Mayan languages + ['', 'myv'], // Erzya + ['', 'nah'], // Nahuatl languages + ['', 'nai'], // North American Indian languages + ['', 'nap'], // Neapolitan + ['na', 'nau'], // Nauru + ['nv', 'nav'], // Navajo; Navaho + ['nr', 'nbl'], // Ndebele, South; South Ndebele + ['nd', 'nde'], // Ndebele, North; North Ndebele + ['ng', 'ndo'], // Ndonga + ['', 'nds'], // Low German; Low Saxon; German, Low; Saxon, Low + ['ne', 'nep'], // Nepali + ['', 'new'], // Nepal Bhasa; Newari + ['', 'nia'], // Nias + ['', 'nic'], // Niger-Kordofanian languages + ['', 'niu'], // Niuean + ['nn', 'nno'], // Norwegian Nynorsk; Nynorsk, Norwegian + ['nb', 'nob'], // Bokmål, Norwegian; Norwegian Bokmål + ['', 'nog'], // Nogai + ['', 'non'], // Norse, Old + ['no', 'nor'], // Norwegian + ['', 'nqo'], // N'Ko + ['', 'nso'], // Pedi; Sepedi; Northern Sotho + ['', 'nub'], // Nubian languages + ['', 'nwc'], // Classical Newari; Old Newari; Classical Nepal Bhasa + ['ny', 'nya'], // Chichewa; Chewa; Nyanja + ['', 'nym'], // Nyamwezi + ['', 'nyn'], // Nyankole + ['', 'nyo'], // Nyoro + ['', 'nzi'], // Nzima + ['oc', 'oci'], // Occitan (post 1500) + ['oj', 'oji'], // Ojibwa + ['or', 'ori'], // Oriya + ['om', 'orm'], // Oromo + ['', 'osa'], // Osage + ['os', 'oss'], // Ossetian; Ossetic + ['', 'ota'], // Turkish, Ottoman (1500-1928) + ['', 'oto'], // Otomian languages + ['', 'paa'], // Papuan languages + ['', 'pag'], // Pangasinan + ['', 'pal'], // Pahlavi + ['', 'pam'], // Pampanga; Kapampangan + ['pa', 'pan'], // Panjabi; Punjabi + ['', 'pap'], // Papiamento + ['', 'pau'], // Palauan + ['', 'peo'], // Persian, Old (ca.600-400 B.C.) + ['fa', 'per'], // Persian + ['', 'phi'], // Philippine languages + ['', 'phn'], // Phoenician + ['pi', 'pli'], // Pali + ['pl', 'pol'], // Polish + ['', 'pon'], // Pohnpeian + ['pt', 'por'], // Portuguese + ['', 'pra'], // Prakrit languages + ['', 'pro'], // Provençal, Old (to 1500); Occitan, Old (to 1500) + ['ps', 'pus'], // Pushto; Pashto + ['', 'qaaqtz'], // Reserved for local use + ['qu', 'que'], // Quechua + ['', 'raj'], // Rajasthani + ['', 'rap'], // Rapanui + ['', 'rar'], // Rarotongan; Cook Islands Maori + ['', 'roa'], // Romance languages + ['rm', 'roh'], // Romansh + ['', 'rom'], // Romany + ['ro', 'rum'], // Romanian; Moldavian; Moldovan + ['rn', 'run'], // Rundi + ['', 'rup'], // Aromanian; Arumanian; Macedo-Romanian + ['ru', 'rus'], // Russian + ['', 'sad'], // Sandawe + ['sg', 'sag'], // Sango + ['', 'sah'], // Yakut + ['', 'sai'], // South American Indian languages + ['', 'sal'], // Salishan languages + ['', 'sam'], // Samaritan Aramaic + ['sa', 'san'], // Sanskrit + ['', 'sas'], // Sasak + ['', 'sat'], // Santali + ['', 'scn'], // Sicilian + ['', 'sco'], // Scots + ['', 'sel'], // Selkup + ['', 'sem'], // Semitic languages + ['', 'sga'], // Irish, Old (to 900) + ['', 'sgn'], // Sign Languages + ['', 'shn'], // Shan + ['', 'sid'], // Sidamo + ['si', 'sin'], // Sinhala; Sinhalese + ['', 'sio'], // Siouan languages + ['', 'sit'], // Sino-Tibetan languages + ['', 'sla'], // Slavic languages + ['sk', 'slo'], // Slovak + ['sl', 'slv'], // Slovenian + ['', 'sma'], // Southern Sami + ['se', 'sme'], // Northern Sami + ['', 'smi'], // Sami languages + ['', 'smj'], // Lule Sami + ['', 'smn'], // Inari Sami + ['sm', 'smo'], // Samoan + ['', 'sms'], // Skolt Sami + ['sn', 'sna'], // Shona + ['sd', 'snd'], // Sindhi + ['', 'snk'], // Soninke + ['', 'sog'], // Sogdian + ['so', 'som'], // Somali + ['', 'son'], // Songhai languages + ['st', 'sot'], // Sotho, Southern + ['es', 'spa'], // Spanish; Castilian + ['sc', 'srd'], // Sardinian + ['', 'srn'], // Sranan Tongo + ['sr', 'srp'], // Serbian + ['', 'srr'], // Serer + ['', 'ssa'], // Nilo-Saharan languages + ['ss', 'ssw'], // Swati + ['', 'suk'], // Sukuma + ['su', 'sun'], // Sundanese + ['', 'sus'], // Susu + ['', 'sux'], // Sumerian + ['sw', 'swa'], // Swahili + ['sv', 'swe'], // Swedish + ['', 'syc'], // Classical Syriac + ['', 'syr'], // Syriac + ['ty', 'tah'], // Tahitian + ['', 'tai'], // Tai languages + ['ta', 'tam'], // Tamil + ['tt', 'tat'], // Tatar + ['te', 'tel'], // Telugu + ['', 'tem'], // Timne + ['', 'ter'], // Tereno + ['', 'tet'], // Tetum + ['tg', 'tgk'], // Tajik + ['tl', 'tgl'], // Tagalog + ['th', 'tha'], // Thai + ['bo', 'tib'], // Tibetan + ['', 'tig'], // Tigre + ['ti', 'tir'], // Tigrinya + ['', 'tiv'], // Tiv + ['', 'tkl'], // Tokelau + ['', 'tlh'], // Klingon; tlhIngan-Hol + ['', 'tli'], // Tlingit + ['', 'tmh'], // Tamashek + ['', 'tog'], // Tonga (Nyasa) + ['to', 'ton'], // Tonga (Tonga Islands) + ['', 'tpi'], // Tok Pisin + ['', 'tsi'], // Tsimshian + ['tn', 'tsn'], // Tswana + ['ts', 'tso'], // Tsonga + ['tk', 'tuk'], // Turkmen + ['', 'tum'], // Tumbuka + ['', 'tup'], // Tupi languages + ['tr', 'tur'], // Turkish + ['', 'tut'], // Altaic languages + ['', 'tvl'], // Tuvalu + ['tw', 'twi'], // Twi + ['', 'tyv'], // Tuvinian + ['', 'udm'], // Udmurt + ['', 'uga'], // Ugaritic + ['ug', 'uig'], // Uighur; Uyghur + ['uk', 'ukr'], // Ukrainian + ['', 'umb'], // Umbundu + ['', 'und'], // Undetermined + ['ur', 'urd'], // Urdu + ['uz', 'uzb'], // Uzbek + ['', 'vai'], // Vai + ['ve', 'ven'], // Venda + ['vi', 'vie'], // Vietnamese + ['vo', 'vol'], // Volapük + ['', 'vot'], // Votic + ['', 'wak'], // Wakashan languages + ['', 'wal'], // Wolaitta; Wolaytta + ['', 'war'], // Waray + ['', 'was'], // Washo + ['cy', 'wel'], // Welsh + ['', 'wen'], // Sorbian languages + ['wa', 'wln'], // Walloon + ['wo', 'wol'], // Wolof + ['', 'xal'], // Kalmyk; Oirat + ['xh', 'xho'], // Xhosa + ['', 'yao'], // Yao + ['', 'yap'], // Yapese + ['yi', 'yid'], // Yiddish + ['yo', 'yor'], // Yoruba + ['', 'ypk'], // Yupik languages + ['', 'zap'], // Zapotec + ['', 'zbl'], // Blissymbols; Blissymbolics; Bliss + ['', 'zen'], // Zenaga + ['', 'zgh'], // Standard Moroccan Tamazight + ['za', 'zha'], // Zhuang; Chuang + ['', 'znd'], // Zande languages + ['zu', 'zul'], // Zulu + ['', 'zun'], // Zuni + ['', 'zxx'], // No linguistic content; Not applicable + // phpcs:enable Squiz.PHP.CommentedOutCode.Found + ]; + + /** + * Initializes the rule defining the ISO 639 set. + * + * @throws ComponentException + */ + public function __construct(string $set = self::ALPHA2) + { + $index = array_search($set, self::AVAILABLE_SETS, true); + if ($index === false) { + throw new ComponentException(sprintf('"%s" is not a valid language set for ISO 639', $set)); + } + + parent::__construct(new In($this->getHaystack($index), true), ['set' => $set]); + } + + /** + * @return string[] + */ + private function getHaystack(int $index): array + { + return array_filter(array_column(self::LANGUAGE_CODES, $index)); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/LeapDate.php b/cacme/vendor/workerman/validation/library/Rules/LeapDate.php new file mode 100644 index 0000000..fa432a8 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/LeapDate.php @@ -0,0 +1,54 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use DateTimeImmutable; +use DateTimeInterface; + +use function is_scalar; + +/** + * Validates if a date is leap. + * + * @author Danilo Benevides + * @author Henrique Moody + * @author Jayson Reis + */ +final class LeapDate extends AbstractRule +{ + /** + * @var string + */ + private $format; + + /** + * Initializes the rule with the expected format. + */ + public function __construct(string $format) + { + $this->format = $format; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof DateTimeInterface) { + return $input->format('m-d') === '02-29'; + } + + if (is_scalar($input)) { + return $this->validate(DateTimeImmutable::createFromFormat($this->format, (string) $input)); + } + + return false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/LeapYear.php b/cacme/vendor/workerman/validation/library/Rules/LeapYear.php new file mode 100644 index 0000000..0a964bb --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/LeapYear.php @@ -0,0 +1,50 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use DateTimeInterface; + +use function date; +use function is_numeric; +use function is_scalar; +use function sprintf; +use function strtotime; + +/** + * Validates if a year is leap. + * + * @author Danilo Correa + * @author Henrique Moody + * @author Jayson Reis + */ +final class LeapYear extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_numeric($input)) { + $date = strtotime(sprintf('%d-02-29', (int) $input)); + + return (bool) date('L', (int) $date); + } + + if (is_scalar($input)) { + return $this->validate((int) date('Y', (int) strtotime((string) $input))); + } + + if ($input instanceof DateTimeInterface) { + return $this->validate($input->format('Y')); + } + + return false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Length.php b/cacme/vendor/workerman/validation/library/Rules/Length.php new file mode 100644 index 0000000..b815db1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Length.php @@ -0,0 +1,130 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Countable as CountableInterface; +use Respect\Validation\Exceptions\ComponentException; + +use function count; +use function get_object_vars; +use function is_array; +use function is_int; +use function is_object; +use function is_string; +use function mb_strlen; +use function sprintf; + +/** + * Validates the length of the given input. + * + * @author Alexandre Gomes Gaigalas + * @author Blake Hair + * @author Danilo Correa + * @author Henrique Moody + * @author Hugo Hamon + * @author João Torquato + * @author Marcelo Araujo + */ +final class Length extends AbstractRule +{ + /** + * @var int|null + */ + private $minValue; + + /** + * @var int|null + */ + private $maxValue; + + /** + * @var bool + */ + private $inclusive; + + /** + * Creates the rule with a minimum and maximum value. + * + * @throws ComponentException + */ + public function __construct(?int $min = null, ?int $max = null, bool $inclusive = true) + { + $this->minValue = $min; + $this->maxValue = $max; + $this->inclusive = $inclusive; + + if ($max !== null && $min > $max) { + throw new ComponentException(sprintf('%d cannot be less than %d for validation', $min, $max)); + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + $length = $this->extractLength($input); + if ($length === null) { + return false; + } + + return $this->validateMin($length) && $this->validateMax($length); + } + + /** + * @param mixed $input + */ + private function extractLength($input): ?int + { + if (is_string($input)) { + return (int) mb_strlen($input); + } + + if (is_array($input) || $input instanceof CountableInterface) { + return count($input); + } + + if (is_object($input)) { + return $this->extractLength(get_object_vars($input)); + } + + if (is_int($input)) { + return $this->extractLength((string) $input); + } + + return null; + } + + private function validateMin(int $length): bool + { + if ($this->minValue === null) { + return true; + } + + if ($this->inclusive) { + return $length >= $this->minValue; + } + + return $length > $this->minValue; + } + + private function validateMax(int $length): bool + { + if ($this->maxValue === null) { + return true; + } + + if ($this->inclusive) { + return $length <= $this->maxValue; + } + + return $length < $this->maxValue; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/LessThan.php b/cacme/vendor/workerman/validation/library/Rules/LessThan.php new file mode 100644 index 0000000..f55e034 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/LessThan.php @@ -0,0 +1,26 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates whether the input is less than a value. + * + * @author Henrique Moody + */ +final class LessThan extends AbstractComparison +{ + /** + * {@inheritDoc} + */ + protected function compare($left, $right): bool + { + return $left < $right; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Lowercase.php b/cacme/vendor/workerman/validation/library/Rules/Lowercase.php new file mode 100644 index 0000000..9318fa4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Lowercase.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function mb_strtolower; + +/** + * Validates whether the characters in the input are lowercase. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class Lowercase extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return $input === mb_strtolower($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Luhn.php b/cacme/vendor/workerman/validation/library/Rules/Luhn.php new file mode 100644 index 0000000..e5c0cec --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Luhn.php @@ -0,0 +1,58 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_map; +use function count; +use function str_split; + +/** + * Validate whether a given input is a Luhn number. + * + * @see https://en.wikipedia.org/wiki/Luhn_algorithm + * + * @author Alexander Gorshkov + * @author Danilo Correa + * @author Henrique Moody + */ +final class Luhn extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!(new Digit())->validate($input)) { + return false; + } + + return $this->isValid((string) $input); + } + + private function isValid(string $input): bool + { + $sum = 0; + $digits = array_map('intval', str_split($input)); + $numDigits = count($digits); + $parity = $numDigits % 2; + for ($i = 0; $i < $numDigits; ++$i) { + $digit = $digits[$i]; + if ($parity == $i % 2) { + $digit <<= 1; + if (9 < $digit) { + $digit = $digit - 9; + } + } + $sum += $digit; + } + + return $sum % 10 == 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/MacAddress.php b/cacme/vendor/workerman/validation/library/Rules/MacAddress.php new file mode 100644 index 0000000..f82a583 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/MacAddress.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function preg_match; + +/** + * Validates whether the input is a valid MAC address. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Fábio da Silva Ribeiro + * @author Henrique Moody + */ +final class MacAddress extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return preg_match('/^(([0-9a-fA-F]{2}-){5}|([0-9a-fA-F]{2}:){5})[0-9a-fA-F]{2}$/', $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Max.php b/cacme/vendor/workerman/validation/library/Rules/Max.php new file mode 100644 index 0000000..f3a2aeb --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Max.php @@ -0,0 +1,27 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates whether the input is less than or equal to a value. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class Max extends AbstractComparison +{ + /** + * {@inheritDoc} + */ + protected function compare($left, $right): bool + { + return $left <= $right; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/MaxAge.php b/cacme/vendor/workerman/validation/library/Rules/MaxAge.php new file mode 100644 index 0000000..fbbd8f5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/MaxAge.php @@ -0,0 +1,27 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates a maximum age for a given date. + * + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class MaxAge extends AbstractAge +{ + /** + * {@inheritDoc} + */ + protected function compare(int $baseDate, int $givenDate): bool + { + return $baseDate <= $givenDate; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Mimetype.php b/cacme/vendor/workerman/validation/library/Rules/Mimetype.php new file mode 100644 index 0000000..05a537e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Mimetype.php @@ -0,0 +1,66 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use finfo; +use SplFileInfo; + +use function is_file; +use function is_string; + +use const FILEINFO_MIME_TYPE; + +/** + * Validates if the input is a file and if its MIME type matches the expected one. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class Mimetype extends AbstractRule +{ + /** + * @var string + */ + private $mimetype; + + /** + * @var finfo + */ + private $fileInfo; + + /** + * Initializes the rule by defining the expected mimetype from the input. + */ + public function __construct(string $mimetype, ?finfo $fileInfo = null) + { + $this->mimetype = $mimetype; + $this->fileInfo = $fileInfo ?: new finfo(); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $this->validate($input->getPathname()); + } + + if (!is_string($input)) { + return false; + } + + if (!is_file($input)) { + return false; + } + + return $this->mimetype === $this->fileInfo->file($input, FILEINFO_MIME_TYPE); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Min.php b/cacme/vendor/workerman/validation/library/Rules/Min.php new file mode 100644 index 0000000..a89bf7b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Min.php @@ -0,0 +1,27 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates whether the input is greater than or equal to a value. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class Min extends AbstractComparison +{ + /** + * {@inheritDoc} + */ + protected function compare($left, $right): bool + { + return $left >= $right; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/MinAge.php b/cacme/vendor/workerman/validation/library/Rules/MinAge.php new file mode 100644 index 0000000..7b2a64e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/MinAge.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates a minimum age for a given date. + * + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Jean Pimentel + * @author Kennedy Tedesco + */ +final class MinAge extends AbstractAge +{ + /** + * {@inheritDoc} + */ + protected function compare(int $baseDate, int $givenDate): bool + { + return $baseDate >= $givenDate; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Mobile.php b/cacme/vendor/workerman/validation/library/Rules/Mobile.php new file mode 100644 index 0000000..f7a69a0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Mobile.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class Multiple extends AbstractRule +{ + /** + * @var int + */ + private $multipleOf; + + public function __construct(int $multipleOf) + { + $this->multipleOf = $multipleOf; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->multipleOf == 0) { + return $input == 0; + } + + return $input % $this->multipleOf == 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Negative.php b/cacme/vendor/workerman/validation/library/Rules/Negative.php new file mode 100644 index 0000000..937a5dd --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Negative.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_numeric; + +/** + * Validates whether the input is a negative number. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Ismael Elias + */ +final class Negative extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input)) { + return false; + } + + return $input < 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NfeAccessKey.php b/cacme/vendor/workerman/validation/library/Rules/NfeAccessKey.php new file mode 100644 index 0000000..fb74f2a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NfeAccessKey.php @@ -0,0 +1,56 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_map; +use function floor; +use function mb_strlen; +use function str_split; + +/** + * Validates the access key of the Brazilian electronic invoice (NFe). + * + * + * (pt-br) Valida chave de acesso de NFe, mais especificamente, relacionada ao DANFE. + * + * @see (pt-br) Manual de Integração do Contribuinte v4.0.1 em http://www.nfe.fazenda.gov.br + * + * @author Andrey Knupp Vital + * @author Danilo Correa + * @author Henrique Moody + */ +final class NfeAccessKey extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (mb_strlen($input) !== 44) { + return false; + } + + $digits = array_map('intval', str_split($input)); + $w = []; + for ($i = 0, $z = 5, $m = 43; $i <= $m; ++$i) { + $z = $i < $m ? $z - 1 == 1 ? 9 : $z - 1 : 0; + $w[] = $z; + } + + for ($i = 0, $s = 0, $k = 44; $i < $k; ++$i) { + $s += $digits[$i] * $w[$i]; + } + + $s -= 11 * floor($s / 11); + $v = $s == 0 || $s == 1 ? 0 : 11 - $s; + + return $v == $digits[43]; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Nif.php b/cacme/vendor/workerman/validation/library/Rules/Nif.php new file mode 100644 index 0000000..f47bcf0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Nif.php @@ -0,0 +1,99 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_pop; +use function array_sum; +use function is_numeric; +use function is_string; +use function mb_substr; +use function preg_match; +use function str_split; + +/** + * Validates Spain's fiscal identification number (NIF). + * + * + * @see https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal + * + * @author Henrique Moody + * @author Julián Gutiérrez + * @author Senén + */ +final class Nif extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + if (preg_match('/^(\d{8})([A-Z])$/', $input, $matches)) { + return $this->validateDni((int) $matches[1], $matches[2]); + } + + if (preg_match('/^([KLMXYZ])(\d{7})([A-Z])$/', $input, $matches)) { + return $this->validateNie($matches[1], $matches[2], $matches[3]); + } + + if (preg_match('/^([A-HJNP-SUVW])(\d{7})([0-9A-Z])$/', $input, $matches)) { + return $this->validateCif($matches[2], $matches[3]); + } + + return false; + } + + private function validateDni(int $number, string $control): bool + { + return mb_substr('TRWAGMYFPDXBNJZSQVHLCKE', $number % 23, 1) === $control; + } + + private function validateNie(string $prefix, string $number, string $control): bool + { + if ($prefix === 'Y') { + return $this->validateDni((int) ('1' . $number), $control); + } + + if ($prefix === 'Z') { + return $this->validateDni((int) ('2' . $number), $control); + } + + return $this->validateDni((int) $number, $control); + } + + private function validateCif(string $number, string $control): bool + { + $code = 0; + $position = 1; + /** @var int $digit */ + foreach (str_split($number) as $digit) { + $increaser = $digit; + if ($position % 2 !== 0) { + $increaser = array_sum(str_split((string) ($digit * 2))); + } + + $code += $increaser; + ++$position; + } + + $digits = str_split((string) $code); + $lastDigit = (int) array_pop($digits); + $key = $lastDigit === 0 ? 0 : 10 - $lastDigit; + + if (is_numeric($control)) { + return (int) $key === (int) $control; + } + + return mb_substr('JABCDEFGHI', $key % 10, 1) === $control; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Nip.php b/cacme/vendor/workerman/validation/library/Rules/Nip.php new file mode 100644 index 0000000..66bb76e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Nip.php @@ -0,0 +1,54 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_map; +use function is_scalar; +use function preg_match; +use function str_split; + +/** + * Validates whether the input is a Polish VAT identification number (NIP). + * + * @see https://en.wikipedia.org/wiki/VAT_identification_number + * + * @author Henrique Moody + * @author Tomasz Regdos + */ +final class Nip extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + if (!preg_match('/^\d{10}$/', (string) $input)) { + return false; + } + + $weights = [6, 5, 7, 2, 3, 4, 5, 6, 7]; + $digits = array_map('intval', str_split((string) $input)); + + $targetControlNumber = $digits[9]; + $calculateControlNumber = 0; + + for ($i = 0; $i < 9; ++$i) { + $calculateControlNumber += $digits[$i] * $weights[$i]; + } + + $calculateControlNumber = $calculateControlNumber % 11; + + return $targetControlNumber == $calculateControlNumber; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/No.php b/cacme/vendor/workerman/validation/library/Rules/No.php new file mode 100644 index 0000000..73f993b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/No.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function nl_langinfo; + +use const NOEXPR; + +/** + * Validates if value is considered as "No". + * + * @author Henrique Moody + */ +final class No extends AbstractEnvelope +{ + public function __construct(bool $useLocale = false) + { + $pattern = '^n(o(t|pe)?|ix|ay)?$'; + if ($useLocale) { + $pattern = nl_langinfo(NOEXPR); + } + + parent::__construct(new Regex('/' . $pattern . '/i')); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NoWhitespace.php b/cacme/vendor/workerman/validation/library/Rules/NoWhitespace.php new file mode 100644 index 0000000..c8d848b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NoWhitespace.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_null; +use function is_scalar; +use function preg_match; + +/** + * Validates whether a string contains no whitespace (spaces, tabs and line breaks). + * + * @author Alexandre Gomes Gaigalas + * @author Augusto Pascutti + * @author Danilo Benevides + * @author Henrique Moody + */ +final class NoWhitespace extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_null($input)) { + return true; + } + + if (is_scalar($input) === false) { + return false; + } + + return !preg_match('#\s#', (string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NoneOf.php b/cacme/vendor/workerman/validation/library/Rules/NoneOf.php new file mode 100644 index 0000000..80adde7 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NoneOf.php @@ -0,0 +1,52 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\NoneOfException; + +use function count; + +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class NoneOf extends AbstractComposite +{ + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $exceptions = $this->getAllThrownExceptions($input); + $numRules = count($this->getRules()); + $numExceptions = count($exceptions); + if ($numRules !== $numExceptions) { + /** @var NoneOfException $noneOfException */ + $noneOfException = $this->reportError($input); + $noneOfException->addChildren($exceptions); + + throw $noneOfException; + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + foreach ($this->getRules() as $rule) { + if ($rule->validate($input)) { + return false; + } + } + + return true; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Not.php b/cacme/vendor/workerman/validation/library/Rules/Not.php new file mode 100644 index 0000000..919a902 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Not.php @@ -0,0 +1,128 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\NonNegatable; +use Respect\Validation\Validatable; + +use function array_shift; +use function count; +use function current; +use function get_class; +use function sprintf; + +/** + * @author Alexandre Gomes Gaigalas + * @author Caio César Tavares + * @author Henrique Moody + */ +final class Not extends AbstractRule +{ + /** + * @var Validatable + */ + private $rule; + + public function __construct(Validatable $rule) + { + $this->rule = $this->extractNegatedRule($rule); + } + + public function getNegatedRule(): Validatable + { + return $this->rule; + } + + public function setName(string $name): Validatable + { + $this->rule->setName($name); + + return parent::setName($name); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $this->rule->validate($input) === false; + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if ($this->validate($input)) { + return; + } + + $rule = $this->rule; + if ($rule instanceof AllOf) { + $rule = $this->absorbAllOf($rule, $input); + } + + $exception = $rule->reportError($input); + $exception->updateMode(ValidationException::MODE_NEGATIVE); + + throw $exception; + } + + /** + * @param mixed $input + */ + private function absorbAllOf(AllOf $rule, $input): Validatable + { + $rules = $rule->getRules(); + while (($current = array_shift($rules))) { + $rule = $current; + if (!$rule instanceof AllOf) { + continue; + } + + if (!$rule->validate($input)) { + continue; + } + + $rules = $rule->getRules(); + } + + return $rule; + } + + private function extractNegatedRule(Validatable $rule): Validatable + { + if ($rule instanceof NonNegatable) { + throw new ComponentException( + sprintf( + '"%s" can not be wrapped in Not()', + get_class($rule) + ) + ); + } + + if ($rule instanceof self && $rule->getNegatedRule() instanceof self) { + return $this->extractNegatedRule($rule->getNegatedRule()->getNegatedRule()); + } + + if (!$rule instanceof AllOf) { + return $rule; + } + + $rules = $rule->getRules(); + if (count($rules) === 1) { + return $this->extractNegatedRule(current($rules)); + } + + return $rule; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NotBlank.php b/cacme/vendor/workerman/validation/library/Rules/NotBlank.php new file mode 100644 index 0000000..26fc4ea --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NotBlank.php @@ -0,0 +1,51 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use stdClass; + +use function array_filter; +use function is_array; +use function is_numeric; +use function is_string; +use function trim; + +/** + * Validates if the given input is not a blank value (null, zeros, empty strings or empty arrays, recursively). + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class NotBlank extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_numeric($input)) { + return $input != 0; + } + + if (is_string($input)) { + $input = trim($input); + } + + if ($input instanceof stdClass) { + $input = (array) $input; + } + + if (is_array($input)) { + $input = array_filter($input, __METHOD__); + } + + return !empty($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NotEmoji.php b/cacme/vendor/workerman/validation/library/Rules/NotEmoji.php new file mode 100644 index 0000000..87b4ef9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NotEmoji.php @@ -0,0 +1,206 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function implode; +use function is_string; +use function preg_match; + +/** + * Validates if the input does not contain an emoji. + * + * @author Mazen Touati + */ +final class NotEmoji extends AbstractRule +{ + private const RANGES = [ + '\x{0023}\x{FE0F}\x{20E3}', + '\x{0023}\x{20E3}', + '\x{002A}\x{FE0F}\x{20E3}', + '\x{002A}\x{20E3}', + '\x{0030}\x{FE0F}\x{20E3}', + '\x{0030}\x{20E3}', + '\x{0031}\x{FE0F}\x{20E3}', + '\x{0031}\x{20E3}', + '\x{0032}\x{FE0F}\x{20E3}', + '\x{0032}\x{20E3}', + '\x{0033}\x{FE0F}\x{20E3}', + '\x{0033}\x{20E3}', + '\x{0034}\x{FE0F}\x{20E3}', + '\x{0034}\x{20E3}', + '\x{0035}\x{FE0F}\x{20E3}', + '\x{0035}\x{20E3}', + '\x{0036}\x{FE0F}\x{20E3}', + '\x{0036}\x{20E3}', + '\x{0037}\x{FE0F}\x{20E3}', + '\x{0037}\x{20E3}', + '\x{0038}\x{FE0F}\x{20E3}', + '\x{0038}\x{20E3}', + '\x{0039}\x{FE0F}\x{20E3}', + '\x{0039}\x{20E3}', + '\x{1F004}', + '\x{1F0CF}', + '[\x{1F170}-\x{1F171}]', + '[\x{1F17E}-\x{1F17F}]', + '\x{1F18E}', + '[\x{1F191}-\x{1F19A}]', + '[\x{1F1E6}-\x{1F1FF}]', + '[\x{1F201}-\x{1F202}]', + '\x{1F21A}', + '\x{1F22F}', + '[\x{1F232}-\x{1F23A}]', + '[\x{1F250}-\x{1F251}]', + '[\x{1F300}-\x{1F321}]', + '[\x{1F324}-\x{1F393}]', + '[\x{1F396}-\x{1F397}]', + '[\x{1F399}-\x{1F39B}]', + '[\x{1F39E}-\x{1F3F0}]', + '[\x{1F3F3}-\x{1F3F5}]', + '[\x{1F3F7}-\x{1F4FD}]', + '[\x{1F4FF}-\x{1F53D}]', + '[\x{1F549}-\x{1F54E}]', + '[\x{1F550}-\x{1F567}]', + '[\x{1F56F}-\x{1F570}]', + '[\x{1F573}-\x{1F57A}]', + '\x{1F587}', + '[\x{1F58A}-\x{1F58D}]', + '\x{1F590}', + '[\x{1F595}-\x{1F596}]', + '[\x{1F5A4}-\x{1F5A5}]', + '\x{1F5A8}', + '[\x{1F5B1}-\x{1F5B2}]', + '\x{1F5BC}', + '[\x{1F5C2}-\x{1F5C4}]', + '[\x{1F5D1}-\x{1F5D3}]', + '[\x{1F5DC}-\x{1F5DE}]', + '\x{1F5E1}', + '\x{1F5E3}', + '\x{1F5E8}', + '\x{1F5EF}', + '\x{1F5F3}', + '[\x{1F5FA}-\x{1F64F}]', + '[\x{1F680}-\x{1F6C5}]', + '[\x{1F6CB}-\x{1F6D2}]', + '[\x{1F6E0}-\x{1F6E5}]', + '\x{1F6E9}', + '[\x{1F6EB}-\x{1F6EC}]', + '\x{1F6F0}', + '[\x{1F6F3}-\x{1F6F9}]', + '[\x{1F910}-\x{1F93A}]', + '[\x{1F93C}-\x{1F93E}]', + '[\x{1F940}-\x{1F945}]', + '[\x{1F947}-\x{1F970}]', + '[\x{1F973}-\x{1F976}]', + '\x{1F97A}', + '[\x{1F97C}-\x{1F9A2}]', + '[\x{1F9B0}-\x{1F9B9}]', + '[\x{1F9C0}-\x{1F9C2}]', + '[\x{1F9D0}-\x{1F9FF}]', + '\x{00A9}', + '\x{00AE}', + '\x{203C}', + '\x{2049}', + '\x{2122}', + '\x{2139}', + '[\x{2194}-\x{2199}]', + '[\x{21A9}-\x{21AA}]', + '[\x{231A}-\x{231B}]', + '\x{2328}', + '\x{23CF}', + '[\x{23E9}-\x{23F3}]', + '[\x{23F8}-\x{23FA}]', + '\x{24C2}', + '[\x{25AA}-\x{25AB}]', + '\x{25B6}', + '\x{25C0}', + '[\x{25FB}-\x{25FE}]', + '[\x{2600}-\x{2604}]', + '\x{260E}', + '\x{2611}', + '[\x{2614}-\x{2615}]', + '\x{2618}', + '\x{261D}', + '\x{2620}', + '[\x{2622}-\x{2623}]', + '\x{2626}', + '\x{262A}', + '[\x{262E}-\x{262F}]', + '[\x{2638}-\x{263A}]', + '\x{2640}', + '\x{2642}', + '[\x{2648}-\x{2653}]', + '[\x{265F}-\x{2660}]', + '\x{2663}', + '[\x{2665}-\x{2666}]', + '\x{2668}', + '\x{267B}', + '[\x{267E}-\x{267F}]', + '[\x{2692}-\x{2697}]', + '\x{2699}', + '[\x{269B}-\x{269C}]', + '[\x{26A0}-\x{26A1}]', + '[\x{26AA}-\x{26AB}]', + '[\x{26B0}-\x{26B1}]', + '[\x{26BD}-\x{26BE}]', + '[\x{26C4}-\x{26C5}]', + '\x{26C8}', + '[\x{26CE}-\x{26CF}]', + '\x{26D1}', + '[\x{26D3}-\x{26D4}]', + '\x{26EA}', + '[\x{26F0}-\x{26F5}]', + '[\x{26F7}-\x{26FA}]', + '\x{26FD}', + '\x{2702}', + '\x{2705}', + '[\x{2708}-\x{270D}]', + '\x{270F}', + '\x{2712}', + '\x{2714}', + '\x{2716}', + '\x{271D}', + '\x{2721}', + '\x{2728}', + '[\x{2733}-\x{2734}]', + '\x{2744}', + '\x{2747}', + '\x{26E9}', + '\x{274C}', + '\x{274E}', + '[\x{2753}-\x{2755}]', + '\x{2757}', + '[\x{2763}-\x{2764}]', + '[\x{2795}-\x{2797}]', + '\x{27A1}', + '\x{27B0}', + '\x{27BF}', + '[\x{2934}-\x{2935}]', + '[\x{2B05}-\x{2B07}]', + '[\x{2B1B}-\x{2B1C}]', + '\x{2B50}', + '\x{2B55}', + '\x{3030}', + '\x{303D}', + '\x{3297}', + '\x{3299}', + ]; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return preg_match('/' . implode('|', self::RANGES) . '/mu', $input) === 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NotEmpty.php b/cacme/vendor/workerman/validation/library/Rules/NotEmpty.php new file mode 100644 index 0000000..2faaadc --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NotEmpty.php @@ -0,0 +1,35 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function trim; + +/** + * Validates whether the input is not empty + * + * @author Alexandre Gomes Gaigalas + * @author Bram Van der Sype + * @author Henrique Moody + */ +final class NotEmpty extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (is_string($input)) { + $input = trim($input); + } + + return !empty($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NotOptional.php b/cacme/vendor/workerman/validation/library/Rules/NotOptional.php new file mode 100644 index 0000000..59fec58 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NotOptional.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CanValidateUndefined; + +/** + * Validates if the given input is not optional. + * + * By optional we consider null or an empty string (''). + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class NotOptional extends AbstractRule +{ + use CanValidateUndefined; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return $this->isUndefined($input) === false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NullType.php b/cacme/vendor/workerman/validation/library/Rules/NullType.php new file mode 100644 index 0000000..cd64750 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NullType.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_null; + +/** + * Validates whether the input is null. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class NullType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_null($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Nullable.php b/cacme/vendor/workerman/validation/library/Rules/Nullable.php new file mode 100644 index 0000000..526044c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Nullable.php @@ -0,0 +1,54 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates the given input with a defined rule when input is not NULL. + * + * @author Jens Segers + */ +final class Nullable extends AbstractWrapper +{ + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if ($input === null) { + return; + } + + parent::assert($input); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + if ($input === null) { + return; + } + + parent::check($input); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input === null) { + return true; + } + + return parent::validate($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Number.php b/cacme/vendor/workerman/validation/library/Rules/Number.php new file mode 100644 index 0000000..6d6ac9f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Number.php @@ -0,0 +1,35 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_nan; +use function is_numeric; + +/** + * Validates if the input is a number. + * + * @author Henrique Moody + * @author Ismael Elias + * @author Vitaliy + */ +final class Number extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input)) { + return false; + } + + return !is_nan((float) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/NumericVal.php b/cacme/vendor/workerman/validation/library/Rules/NumericVal.php new file mode 100644 index 0000000..0502999 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/NumericVal.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_numeric; + +/** + * Validates whether the input is numeric. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Henrique Moody + */ +final class NumericVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_numeric($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/ObjectType.php b/cacme/vendor/workerman/validation/library/Rules/ObjectType.php new file mode 100644 index 0000000..747b1cb --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/ObjectType.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_object; + +/** + * Validates whether the input is an object. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class ObjectType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_object($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Odd.php b/cacme/vendor/workerman/validation/library/Rules/Odd.php new file mode 100644 index 0000000..658260a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Odd.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function filter_var; +use function is_numeric; + +use const FILTER_VALIDATE_INT; + +/** + * Validates whether the input is an odd number or not. + * + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class Odd extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input)) { + return false; + } + + if (!filter_var($input, FILTER_VALIDATE_INT)) { + return false; + } + + return (int) $input % 2 !== 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/OneOf.php b/cacme/vendor/workerman/validation/library/Rules/OneOf.php new file mode 100644 index 0000000..e8434e6 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/OneOf.php @@ -0,0 +1,82 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\OneOfException; +use Respect\Validation\Exceptions\ValidationException; + +use function array_shift; +use function count; + +/** + * @author Bradyn Poulsen + * @author Henrique Moody + */ +final class OneOf extends AbstractComposite +{ + /** + * {@inheritDoc} + */ + public function assert($input): void + { + $validators = $this->getRules(); + $exceptions = $this->getAllThrownExceptions($input); + $numRules = count($validators); + $numExceptions = count($exceptions); + if ($numExceptions !== $numRules - 1) { + /** @var OneOfException $oneOfException */ + $oneOfException = $this->reportError($input); + $oneOfException->addChildren($exceptions); + + throw $oneOfException; + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + $rulesPassedCount = 0; + foreach ($this->getRules() as $rule) { + if (!$rule->validate($input)) { + continue; + } + + ++$rulesPassedCount; + } + + return $rulesPassedCount === 1; + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + $exceptions = []; + $rulesPassedCount = 0; + foreach ($this->getRules() as $rule) { + try { + $rule->check($input); + + ++$rulesPassedCount; + } catch (ValidationException $exception) { + $exceptions[] = $exception; + } + } + + if ($rulesPassedCount === 1) { + return; + } + + throw array_shift($exceptions) ?: $this->reportError($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Optional.php b/cacme/vendor/workerman/validation/library/Rules/Optional.php new file mode 100644 index 0000000..cb666f9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Optional.php @@ -0,0 +1,56 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CanValidateUndefined; + +/** + * @author Henrique Moody + */ +final class Optional extends AbstractWrapper +{ + use CanValidateUndefined; + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if ($this->isUndefined($input)) { + return; + } + + parent::assert($input); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + if ($this->isUndefined($input)) { + return; + } + + parent::check($input); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->isUndefined($input)) { + return true; + } + + return parent::validate($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PerfectSquare.php b/cacme/vendor/workerman/validation/library/Rules/PerfectSquare.php new file mode 100644 index 0000000..204da99 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PerfectSquare.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function floor; +use function is_numeric; +use function sqrt; + +/** + * Validates whether the input is a perfect square. + * + * @author Danilo Benevides + * @author Henrique Moody + * @author Kleber Hamada Sato + * @author Nick Lombard + */ +final class PerfectSquare extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_numeric($input) && floor(sqrt((float) $input)) == sqrt((float) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Pesel.php b/cacme/vendor/workerman/validation/library/Rules/Pesel.php new file mode 100644 index 0000000..48c8227 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Pesel.php @@ -0,0 +1,51 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function preg_match; + +/** + * Validates PESEL (Polish human identification number). + * + * @author Danilo Correa + * @author Henrique Moody + * @author Tomasz Regdos + */ +final class Pesel extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $stringInput = (string) $input; + if (!preg_match('/^\d{11}$/', (string) $stringInput)) { + return false; + } + + $weights = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3]; + + $targetControlNumber = $stringInput[10]; + $calculateControlNumber = 0; + + for ($i = 0; $i < 10; ++$i) { + $calculateControlNumber += (int) $stringInput[$i] * $weights[$i]; + } + + $calculateControlNumber = (10 - $calculateControlNumber % 10) % 10; + + return $targetControlNumber == $calculateControlNumber; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Phone.php b/cacme/vendor/workerman/validation/library/Rules/Phone.php new file mode 100644 index 0000000..5dae4d0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Phone.php @@ -0,0 +1,73 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use libphonenumber\NumberParseException; +use libphonenumber\PhoneNumberUtil; +use Respect\Validation\Exceptions\ComponentException; + +use function class_exists; +use function is_null; +use function is_scalar; +use function sprintf; + +/** + * Validates whether the input is a valid phone number. + * + * Validates an international or country-specific telephone number + * + * @author Alexandre Gomes Gaigalas + */ +final class Phone extends AbstractRule +{ + /** + * @var ?string + */ + private $countryCode; + + /** + * {@inheritDoc} + */ + public function __construct(?string $countryCode = null) + { + $this->countryCode = $countryCode; + + if (!is_null($countryCode) && !(new CountryCode())->validate($countryCode)) { + throw new ComponentException( + sprintf( + 'Invalid country code %s', + $countryCode + ) + ); + } + + if (!class_exists(PhoneNumberUtil::class)) { + throw new ComponentException('The phone validator requires giggsey/libphonenumber-for-php'); + } + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + try { + return PhoneNumberUtil::getInstance()->isValidNumber( + PhoneNumberUtil::getInstance()->parse((string) $input, $this->countryCode) + ); + } catch (NumberParseException $e) { + return false; + } + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PhpLabel.php b/cacme/vendor/workerman/validation/library/Rules/PhpLabel.php new file mode 100644 index 0000000..7f64f77 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PhpLabel.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function preg_match; + +/** + * Validates if a value is considered a valid PHP Label, so that it can be used as a variable, function or class name. + * + * @author Danilo Correa + * @author Emmerson Siqueira + * @author Henrique Moody + */ +final class PhpLabel extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_string($input) && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Pis.php b/cacme/vendor/workerman/validation/library/Rules/Pis.php new file mode 100644 index 0000000..683bd54 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Pis.php @@ -0,0 +1,53 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function mb_strlen; +use function preg_match; +use function preg_replace; + +/** + * Validates a Brazilian PIS/NIS number. + * + * @author Bruno Koga + * @author Danilo Correa + * @author Henrique Moody + */ +final class Pis extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $digits = (string) preg_replace('/\D/', '', (string) $input); + if (mb_strlen($digits) != 11 || preg_match('/^' . $digits[0] . '{11}$/', $digits)) { + return false; + } + + $multipliers = [3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + + $summation = 0; + for ($position = 0; $position < 10; ++$position) { + $summation += (int) $digits[$position] * $multipliers[$position]; + } + + $checkDigit = (int) $digits[10]; + + $modulo = $summation % 11; + + return $checkDigit === ($modulo < 2 ? 0 : 11 - $modulo); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PolishIdCard.php b/cacme/vendor/workerman/validation/library/Rules/PolishIdCard.php new file mode 100644 index 0000000..f8d103d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PolishIdCard.php @@ -0,0 +1,63 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function ord; +use function preg_match; + +/** + * Validates whether the input is a Polish identity card (Dowód Osobisty). + * + * @see https://en.wikipedia.org/wiki/Polish_identity_card + * + * @author Henrique Moody + */ +final class PolishIdCard extends AbstractRule +{ + private const ASCII_CODE_0 = 48; + private const ASCII_CODE_7 = 55; + private const ASCII_CODE_9 = 57; + private const ASCII_CODE_A = 65; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + $input = (string) $input; + + if (!preg_match('/^[A-Z0-9]{9}$/', $input)) { + return false; + } + + $weights = [7, 3, 1, 0, 7, 3, 1, 7, 3]; + $weightedSum = 0; + for ($i = 0; $i < 9; ++$i) { + $code = ord($input[$i]); + if ($i < 3 && $code <= self::ASCII_CODE_9) { + return false; + } + + if ($i > 2 && $code >= self::ASCII_CODE_A) { + return false; + } + + $difference = $code <= self::ASCII_CODE_9 ? self::ASCII_CODE_0 : self::ASCII_CODE_7; + $weightedSum += ($code - $difference) * $weights[$i]; + } + + return $weightedSum % 10 == $input[3]; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PortugueseNif.php b/cacme/vendor/workerman/validation/library/Rules/PortugueseNif.php new file mode 100644 index 0000000..bfbdb6a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PortugueseNif.php @@ -0,0 +1,105 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_keys; +use function array_map; +use function array_pop; +use function array_sum; +use function intval; +use function is_numeric; +use function is_string; +use function str_split; +use function strlen; + +/** + * Validates Portugal's fiscal identification number (NIF) + * + * + * @see https://pt.wikipedia.org/wiki/N%C3%BAmero_de_identifica%C3%A7%C3%A3o_fiscal + * + * @author Gonçalo Andrade + */ +final class PortugueseNif extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + // Validate format and length + if (!is_string($input)) { + return false; + } + + if (!is_numeric($input)) { + return false; + } + + if (strlen($input) != 9) { + return false; + } + + $digits = array_map(static fn (string $digit) => intval($digit), str_split($input)); + + // Validate first and second digits + switch ($digits[0]) { + case 4: + switch ($digits[1]) { + case 5: + break; + default: + return false; + } + break; + case 7: + switch ($digits[1]) { + case 0: + case 1: + case 2: + case 4: + case 5: + case 7: + case 8: + case 9: + break; + default: + return false; + } + break; + case 9: + switch ($digits[1]) { + case 0: + case 1: + case 8: + case 9: + break; + default: + return false; + } + break; + default: + break; + } + + // Validate check digit + $checkDigit = array_pop($digits); + $digitKeys = array_keys($digits); + $sumTerms = array_map(static fn (int $digit, int $position) => $digit * (9 - $position), $digits, $digitKeys); + $sum = array_sum($sumTerms); + $modulus = $sum % 11; + + if ($modulus == 0 || $modulus == 1) { + return $checkDigit == 0; + } + + return $checkDigit == 11 - $modulus; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Positive.php b/cacme/vendor/workerman/validation/library/Rules/Positive.php new file mode 100644 index 0000000..d6857cf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Positive.php @@ -0,0 +1,34 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_numeric; + +/** + * Validates whether the input is a positive number. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Ismael Elias + */ +final class Positive extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input)) { + return false; + } + + return $input > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PostalCode.php b/cacme/vendor/workerman/validation/library/Rules/PostalCode.php new file mode 100644 index 0000000..d86c44a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PostalCode.php @@ -0,0 +1,222 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function sprintf; + +/** + * Validates whether the input is a valid postal code or not. + * + * @see http://download.geonames.org/export/dump/countryInfo.txt + * + * @author Henrique Moody + */ +final class PostalCode extends AbstractEnvelope +{ + private const DEFAULT_PATTERN = '/^$/'; + + private const POSTAL_CODES_EXTRA = [ + // phpcs:disable Generic.Files.LineLength.TooLong + 'AM' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BR' => ['/^\d\d\d\d\d-\d\d\d$/', '/^\d{5}-?\d{3}$/'], + 'EC' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'GR' => ['/^\d\d\d \d\d$/', '/^(\d{3}\s?\d{2})$/'], + 'GB' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR 0AA$/', '/^([Gg][Ii][Rr]\s?0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\s?[0-9][A-Za-z]{2})$/'], + 'KH' => ['/^\d\d\d\d\d\d?$/', '/^(\d{5,6})$/'], + 'KY' => ['/^KY[1-3]-\d{4}$/', '/^KY[1-3]-?\d{4}$/'], + 'PT' => ['/^\d\d\d\d-\d\d\d$/', '/^\d{4}-?\d{3}\s?[a-zA-Z]{0,25}$/'], + 'RS' => ['/^\d\d\d\d\d\d?$/', '/^(\d{5,6})$/'], + // phpcs:enable Generic.Files.LineLength.TooLong + ]; + + private const POSTAL_CODES = [ + // phpcs:disable Generic.Files.LineLength.TooLong + 'AD' => ['/^AD\d\d\d$/', '/^(?:AD)*(\d{3})$/'], + 'AL' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'AM' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'AR' => ['/^\w\d\d\d\d\w\w\w$/', '/^[A-Z]?\d{4}[A-Z]{0,3}$/'], + 'AS' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/96799/'], + 'AT' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'AU' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'AX' => ['/^\d\d\d\d\d$/', '/^(?:FI)*(\d{5})$/'], + 'AZ' => ['/^AZ \d\d\d\d$/', '/^(?:AZ)*(\d{4})$/'], + 'BA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'BB' => ['/^BB\d\d\d\d\d$/', '/^(?:BB)*(\d{5})$/'], + 'BD' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BG' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BH' => ['/^\d\d\d\d|\d\d\d$/', '/^(\d{3}\d?)$/'], + 'BL' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'BM' => ['/^\w\w \d\d$/', '/^([A-Z]{2}\d{2})$/'], + 'BN' => ['/^\w\w\d\d\d\d$/', '/^([A-Z]{2}\d{4})$/'], + 'BR' => ['/^\d\d\d\d\d-\d\d\d$/', '/^\d{5}-\d{3}$/'], + 'BY' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'CA' => ['/^\w\d\w \d\w\d$/', '/^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]) ?(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$/'], + 'CH' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CL' => ['/^\d\d\d\d\d\d\d$/', '/^(\d{7})$/'], + 'CN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'CO' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'CR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'CS' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'CU' => ['/^CP \d\d\d\d\d$/', '/^(?:CP)*(\d{5})$/'], + 'CV' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CX' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CY' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CZ' => ['/^\d\d\d \d\d$/', '/^\d{3}\s?\d{2}$/'], + 'DE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'DK' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'DO' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'DZ' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'EC' => ['/^\w\d\d\d\d\w$/', '/^([a-zA-Z]\d{4}[a-zA-Z])$/'], + 'EE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'EG' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'ES' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'ET' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'FI' => ['/^\d\d\d\d\d$/', '/^(?:FI)*(\d{5})$/'], + 'FM' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'FO' => ['/^\d\d\d$/', '/^(?:FO)*(\d{3})$/'], + 'FR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'GB' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^([Gg][Ii][Rr]\s?0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\s?[0-9][A-Za-z]{2})$/'], + 'GE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'GF' => ['/^\d\d\d\d\d$/', '/^((97|98)3\d{2})$/'], + 'GG' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/'], + 'GL' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'GP' => ['/^\d\d\d\d\d$/', '/^((97|98)\d{3})$/'], + 'GR' => ['/^\d\d\d \d\d$/', '/^(\d{5})$/'], + 'GT' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'GU' => ['/^969\d\d$/', '/^(969\d{2})$/'], + 'GW' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'HN' => ['/^\w\w\d\d\d\d$/', '/^([A-Z]{2}\d{4})$/'], + 'HR' => ['/^\d\d\d\d\d$/', '/^(?:HR)*(\d{5})$/'], + 'HT' => ['/^HT\d\d\d\d$/', '/^(?:HT)*(\d{4})$/'], + 'HU' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'ID' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'IE' => ['/^\w\w\w \w\w\w\w$/', '/^(D6W|[AC-FHKNPRTV-Y][0-9]{2})\s?([AC-FHKNPRTV-Y0-9]{4})/'], + 'IL' => ['/^\d\d\d\d\d\d\d$/', '/^(\d{7}|\d{5})$/'], + 'IM' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/'], + 'IN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'IQ' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'IR' => ['/^\d\d\d\d\d\d\d\d\d\d$/', '/^(\d{10})$/'], + 'IS' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'IT' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'JE' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/'], + 'JO' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'JP' => ['/^\d\d\d-\d\d\d\d$/', '/^\d{3}-\d{4}$/'], + 'KE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KG' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'KH' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KP' => ['/^\d\d\d-\d\d\d$/', '/^(\d{6})$/'], + 'KR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KW' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KZ' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'LA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'LB' => ['/^\d\d\d\d \d\d\d\d|\d\d\d\d$/', '/^(\d{4}(\d{4})?)$/'], + 'LI' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'LK' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'LR' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'LS' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'LT' => ['/^LT-\d\d\d\d\d$/', '/^(?:LT)*(\d{5})$/'], + 'LU' => ['/^L-\d\d\d\d$/', '/^(?:L-)?\d{4}$/'], + 'LV' => ['/^LV-\d\d\d\d$/', '/^(?:LV)*(\d{4})$/'], + 'MA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MC' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MD' => ['/^MD-\d\d\d\d$/', '/^MD-\d{4}$/'], + 'ME' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MF' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MG' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'MH' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^969\d{2}(-\d{4})$/'], + 'MK' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'MM' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'MP' => ['/^\d\d\d\d\d$/', '/^9695\d{1}$/'], + 'MQ' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MT' => ['/^\w\w\w \d\d\d\d$/', '/^[A-Z]{3}\s?\d{4}$/'], + 'MV' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MW' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'MX' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MY' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MZ' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NC' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'NE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NF' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NG' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'NI' => ['/^\d\d\d-\d\d\d-\d$/', '/^(\d{7})$/'], + 'NL' => ['/^\d\d\d\d \w\w$/', '/^(\d{4}\s?[a-zA-Z]{2})$/'], + 'NO' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NP' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'NZ' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'OM' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'PE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'PF' => ['/^\d\d\d\d\d$/', '/^((97|98)7\d{2})$/'], + 'PG' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'PH' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'PK' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'PL' => ['/^\d\d-\d\d\d$/', '/^\d{2}-\d{3}$/'], + 'PM' => ['/^\d\d\d\d\d$/', '/^(97500)$/'], + 'PR' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^00[679]\d{2}(?:-\d{4})?$/'], + 'PT' => ['/^\d\d\d\d-\d\d\d$/', '/^\d{4}-\d{3}\s?[a-zA-Z]{0,25}$/'], + 'PW' => ['/^96940$/', '/^(96940)$/'], + 'PY' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'RE' => ['/^\d\d\d\d\d$/', '/^((97|98)(4|7|8)\d{2})$/'], + 'RO' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'RS' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'RU' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'SA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'SD' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'SE' => ['/^\d\d\d \d\d$/', '/^(?:SE)?\d{3}\s\d{2}$/'], + 'SG' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'SH' => ['/^STHL 1ZZ$/', '/^(STHL1ZZ)$/'], + 'SI' => ['/^\d\d\d\d$/', '/^(?:SI)*(\d{4})$/'], + 'SJ' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'SK' => ['/^\d\d\d \d\d$/', '/^\d{3}\s?\d{2}$/'], + 'SM' => ['/^4789\d$/', '/^(4789\d)$/'], + 'SN' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'SO' => ['/^\w\w \d\d\d\d\d$/', '/^([A-Z]{2}\d{5})$/'], + 'SV' => ['/^CP \d\d\d\d$/', '/^(?:CP)*(\d{4})$/'], + 'SZ' => ['/^\w\d\d\d$/', '/^([A-Z]\d{3})$/'], + 'TC' => ['/^TKCA 1ZZ$/', '/^(TKCA 1ZZ)$/'], + 'TH' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'TJ' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'TM' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'TN' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'TR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'TW' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'UA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'US' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^\d{5}(-\d{4})?$/'], + 'UY' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'UZ' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'VA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'VE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'VI' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^008\d{2}(?:-\d{4})?$/'], + 'VN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'WF' => ['/^\d\d\d\d\d$/', '/^(986\d{2})$/'], + 'YT' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'ZA' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'ZM' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + // phpcs:disable Generic.Files.LineLength.TooLong + ];//end + + public function __construct(string $countryCode, bool $formatted = false) + { + $countryCodeRule = new CountryCode(); + if (!$countryCodeRule->validate($countryCode)) { + throw new ComponentException(sprintf('Cannot validate postal code from "%s" country', $countryCode)); + } + + parent::__construct( + new Regex( + self::POSTAL_CODES_EXTRA[$countryCode][$formatted ? 0 : 1] ?? self::POSTAL_CODES[$countryCode][$formatted ? 0 : 1] ?? self::DEFAULT_PATTERN + ), + ['countryCode' => $countryCode] + ); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PrimeNumber.php b/cacme/vendor/workerman/validation/library/Rules/PrimeNumber.php new file mode 100644 index 0000000..c5aa2f9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PrimeNumber.php @@ -0,0 +1,48 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ceil; +use function is_numeric; +use function sqrt; + +/** + * Validates whether the input is a prime number. + * + * @author Alexandre Gomes Gaigalas + * @author Camilo Teixeira de Melo + * @author Henrique Moody + * @author Ismael Elias + * @author Kleber Hamada Sato + */ +final class PrimeNumber extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_numeric($input) || $input <= 1) { + return false; + } + + if ($input != 2 && ($input % 2) == 0) { + return false; + } + + for ($i = 3; $i <= ceil(sqrt((float) $input)); $i += 2) { + if ($input % $i == 0) { + return false; + } + } + + return true; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Printable.php b/cacme/vendor/workerman/validation/library/Rules/Printable.php new file mode 100644 index 0000000..d757300 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Printable.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_print; + +/** + * Validates whether an input is printable character(s). + * + * @author Alexandre Gomes Gaigalas + * @author Andre Ramaciotti + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Nick Lombard + */ +final class Printable extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_print($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/PublicDomainSuffix.php b/cacme/vendor/workerman/validation/library/Rules/PublicDomainSuffix.php new file mode 100644 index 0000000..67f07ac --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/PublicDomainSuffix.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\DomainInfo; + +use function array_pop; +use function explode; + +final class PublicDomainSuffix extends AbstractSearcher +{ + /** + * @var string[] + */ + private $domainInfo; + + /** + * {@inheritDoc} + */ + protected function getDataSource($input = null): array + { + $parts = explode('.', $input); + $tld = array_pop($parts); + + $domainInfo = new DomainInfo($tld); + $this->domainInfo = $domainInfo->getPublicSuffixes(); + + return $this->domainInfo; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Punct.php b/cacme/vendor/workerman/validation/library/Rules/Punct.php new file mode 100644 index 0000000..6374d51 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Punct.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_punct; + +/** + * Validates whether the input composed by only punctuation characters. + * + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + * @author Nick Lombard + */ +final class Punct extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_punct($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Readable.php b/cacme/vendor/workerman/validation/library/Rules/Readable.php new file mode 100644 index 0000000..c27b9a4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Readable.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Psr\Http\Message\StreamInterface; +use SplFileInfo; + +use function is_readable; +use function is_string; + +/** + * Validates if the given data is a file exists and is readable. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class Readable extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $input->isReadable(); + } + + if ($input instanceof StreamInterface) { + return $input->isReadable(); + } + + return is_string($input) && is_readable($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Regex.php b/cacme/vendor/workerman/validation/library/Rules/Regex.php new file mode 100644 index 0000000..2eba94e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Regex.php @@ -0,0 +1,48 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; +use function preg_match; + +/** + * Validates whether the input matches a defined regular expression. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Henrique Moody + */ +final class Regex extends AbstractRule +{ + /** + * @var string + */ + private $regex; + + /** + * Initializes the rule. + */ + public function __construct(string $regex) + { + $this->regex = $regex; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + return preg_match($this->regex, (string) $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/ResourceType.php b/cacme/vendor/workerman/validation/library/Rules/ResourceType.php new file mode 100644 index 0000000..d5cf062 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/ResourceType.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_resource; + +/** + * Validates whether the input is a resource. + * + * @author Henrique Moody + */ +final class ResourceType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_resource($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Roman.php b/cacme/vendor/workerman/validation/library/Rules/Roman.php new file mode 100644 index 0000000..45cada4 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Roman.php @@ -0,0 +1,25 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +/** + * Validates if the input is a Roman numeral. + * + * @author Alexander Wühr + * @author Henrique Moody + * @author Jean Pimentel + */ +final class Roman extends AbstractEnvelope +{ + public function __construct() + { + parent::__construct(new Regex('/^(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/')); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/ScalarVal.php b/cacme/vendor/workerman/validation/library/Rules/ScalarVal.php new file mode 100644 index 0000000..955303b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/ScalarVal.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_scalar; + +/** + * Validates whether the input is a scalar value or not. + * + * @author Henrique Moody + */ +final class ScalarVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_scalar($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Size.php b/cacme/vendor/workerman/validation/library/Rules/Size.php new file mode 100644 index 0000000..d7e1d47 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Size.php @@ -0,0 +1,124 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Psr\Http\Message\StreamInterface; +use Psr\Http\Message\UploadedFileInterface; +use Respect\Validation\Exceptions\ComponentException; +use SplFileInfo; + +use function filesize; +use function floatval; +use function is_numeric; +use function is_string; +use function preg_match; +use function sprintf; + +/** + * Validates whether the input is a file that is of a certain size or not. + * + * @author Danilo Correa + * @author Henrique Moody + * @author Felipe Stival + */ +final class Size extends AbstractRule +{ + /** + * @var string|int|null + */ + private $minSize; + + /** + * @var float|null + */ + private $minValue; + + /** + * @var string|int|null + */ + private $maxSize; + + /** + * @var float|null + */ + private $maxValue; + + /** + * @param string|int|null $minSize + * @param string|int|null $maxSize + */ + public function __construct($minSize = null, $maxSize = null) + { + $this->minSize = $minSize; + $this->minValue = $minSize ? $this->toBytes((string) $minSize) : null; + $this->maxSize = $maxSize; + $this->maxValue = $maxSize ? $this->toBytes((string) $maxSize) : null; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $this->isValidSize((float) $input->getSize()); + } + + if ($input instanceof UploadedFileInterface) { + return $this->isValidSize((float) $input->getSize()); + } + + if ($input instanceof StreamInterface) { + return $this->isValidSize((float) $input->getSize()); + } + + if (is_string($input)) { + return $this->isValidSize((float) filesize($input)); + } + + return false; + } + + /** + * @todo Move it to a trait + * + */ + private function toBytes(string $size): float + { + $value = $size; + $units = ['b', 'kb', 'mb', 'gb', 'tb', 'pb', 'eb', 'zb', 'yb']; + foreach ($units as $exponent => $unit) { + if (!preg_match('/^(\d+(.\d+)?)' . $unit . '$/i', $size, $matches)) { + continue; + } + $value = floatval($matches[1]) * 1024 ** $exponent; + break; + } + + if (!is_numeric($value)) { + throw new ComponentException(sprintf('"%s" is not a recognized file size.', $size)); + } + + return (float) $value; + } + + private function isValidSize(float $size): bool + { + if ($this->minValue !== null && $this->maxValue !== null) { + return $size >= $this->minValue && $size <= $this->maxValue; + } + + if ($this->minValue !== null) { + return $size >= $this->minValue; + } + + return $size <= $this->maxValue; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Slug.php b/cacme/vendor/workerman/validation/library/Rules/Slug.php new file mode 100644 index 0000000..a8263eb --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Slug.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function mb_strstr; +use function preg_match; + +/** + * Validates whether the input is a valid slug. + * + * @author Carlos André Ferrari + * @author Danilo Correa + * @author Henrique Moody + * @author Nick Lombard + */ +final class Slug extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input) || mb_strstr($input, '--')) { + return false; + } + + if (!preg_match('@^[0-9a-z\-]+$@', $input)) { + return false; + } + + return preg_match('@^-|-$@', $input) === 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Sorted.php b/cacme/vendor/workerman/validation/library/Rules/Sorted.php new file mode 100644 index 0000000..84037f3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Sorted.php @@ -0,0 +1,94 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_values; +use function count; +use function is_array; +use function is_string; +use function sprintf; +use function str_split; + +/** + * Validates whether the input is sorted in a certain order or not. + * + * @author Henrique Moody + * @author Mikhail Vyrtsev + */ +final class Sorted extends AbstractRule +{ + public const ASCENDING = 'ASC'; + public const DESCENDING = 'DESC'; + + /** + * @var string + */ + private $direction; + + public function __construct(string $direction) + { + if ($direction !== self::ASCENDING && $direction !== self::DESCENDING) { + throw new ComponentException( + sprintf('Direction should be either "%s" or "%s"', self::ASCENDING, self::DESCENDING) + ); + } + + $this->direction = $direction; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_array($input) && !is_string($input)) { + return false; + } + + $values = $this->getValues($input); + $count = count($values); + for ($position = 1; $position < $count; ++$position) { + if (!$this->isSorted($values[$position], $values[$position - 1])) { + return false; + } + } + + return true; + } + + /** + * @param mixed $current + * @param mixed $last + */ + private function isSorted($current, $last): bool + { + if ($this->direction === self::ASCENDING) { + return $current > $last; + } + + return $current < $last; + } + + /** + * @param string|mixed[] $input + * + * @return mixed[] + */ + private function getValues($input): array + { + if (is_array($input)) { + return array_values($input); + } + + return str_split($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Space.php b/cacme/vendor/workerman/validation/library/Rules/Space.php new file mode 100644 index 0000000..b7a1eea --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Space.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_space; + +/** + * Validates whether the input contains only whitespaces characters. + * + * @author Andre Ramaciotti + * @author Danilo Correa + * @author Henrique Moody + * @author Nick Lombard + */ +final class Space extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_space($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/StartsWith.php b/cacme/vendor/workerman/validation/library/Rules/StartsWith.php new file mode 100644 index 0000000..dc5e0a3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/StartsWith.php @@ -0,0 +1,89 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_array; +use function is_string; +use function mb_stripos; +use function mb_strpos; +use function reset; + +/** + * Validates whether the input starts with a given value. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + * @author Marcelo Araujo + */ +final class StartsWith extends AbstractRule +{ + /** + * @var mixed + */ + private $startValue; + + /** + * @var bool + */ + private $identical; + + /** + * @param mixed $startValue + */ + public function __construct($startValue, bool $identical = false) + { + $this->startValue = $startValue; + $this->identical = $identical; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->identical) { + return $this->validateIdentical($input); + } + + return $this->validateEquals($input); + } + + /** + * @param mixed $input + */ + protected function validateEquals($input): bool + { + if (is_array($input)) { + return reset($input) == $this->startValue; + } + + if (is_string($input) && is_string($this->startValue)) { + return mb_stripos($input, $this->startValue) === 0; + } + + return false; + } + + /** + * @param mixed $input + */ + protected function validateIdentical($input): bool + { + if (is_array($input)) { + return reset($input) === $this->startValue; + } + + if (is_string($input) && is_string($this->startValue)) { + return mb_strpos($input, $this->startValue) === 0; + } + + return false; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/StringType.php b/cacme/vendor/workerman/validation/library/Rules/StringType.php new file mode 100644 index 0000000..0dce1d5 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/StringType.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; + +/** + * Validates whether the type of an input is string or not. + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class StringType extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_string($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/StringVal.php b/cacme/vendor/workerman/validation/library/Rules/StringVal.php new file mode 100644 index 0000000..469cec9 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/StringVal.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_object; +use function is_scalar; +use function method_exists; + +/** + * Validates whether the input can be used as a string. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class StringVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return is_scalar($input) || (is_object($input) && method_exists($input, '__toString')); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/SubdivisionCode.php b/cacme/vendor/workerman/validation/library/Rules/SubdivisionCode.php new file mode 100644 index 0000000..fe90a54 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/SubdivisionCode.php @@ -0,0 +1,52 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Helpers\CountryInfo; + +use function array_keys; + +/** + * Validates country subdivision codes according to ISO 3166-2. + * + * @see http://en.wikipedia.org/wiki/ISO_3166-2 + * @see http://www.geonames.org/countries/ + * + * @author Henrique Moody + * @author Mazen Touati + */ +final class SubdivisionCode extends AbstractSearcher +{ + /** + * @var string + */ + private $countryName; + + /** + * @var string[] + */ + private $countryInfo; + + public function __construct(string $countryCode) + { + $countryInfo = new CountryInfo($countryCode); + + $this->countryName = $countryInfo->getCountry(); + $this->countryInfo = array_keys($countryInfo->getSubdivisions()); + } + + /** + * {@inheritDoc} + */ + protected function getDataSource($input = null): array + { + return $this->countryInfo; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Subset.php b/cacme/vendor/workerman/validation/library/Rules/Subset.php new file mode 100644 index 0000000..fddc5d1 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Subset.php @@ -0,0 +1,49 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_diff; +use function is_array; + +/** + * Validates whether the input is a subset of a given value. + * + * @author Henrique Moody + * @author Singwai Chan + */ +final class Subset extends AbstractRule +{ + /** + * @var mixed[] + */ + private $superset; + + /** + * Initializes the rule. + * + * @param mixed[] $superset + */ + public function __construct(array $superset) + { + $this->superset = $superset; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_array($input)) { + return false; + } + + return array_diff($input, $this->superset) === []; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/SymbolicLink.php b/cacme/vendor/workerman/validation/library/Rules/SymbolicLink.php new file mode 100644 index 0000000..6fe9d0f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/SymbolicLink.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use SplFileInfo; + +use function is_link; +use function is_string; + +/** + * Validates if the given input is a symbolic link. + * + * @author Henrique Moody + * @author Gus Antoniassi + */ +final class SymbolicLink extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $input->isLink(); + } + + return is_string($input) && is_link($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Time.php b/cacme/vendor/workerman/validation/library/Rules/Time.php new file mode 100644 index 0000000..dc9f646 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Time.php @@ -0,0 +1,66 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Helpers\CanValidateDateTime; + +use function date; +use function is_scalar; +use function preg_match; +use function sprintf; +use function strtotime; + +/** + * Validates whether an input is a time or not + * + * @author Henrique Moody + */ +final class Time extends AbstractRule +{ + use CanValidateDateTime; + + /** + * @var string + */ + private $format; + + /** + * @var string + */ + private $sample; + + /** + * Initializes the rule. + * + * @throws ComponentException + */ + public function __construct(string $format = 'H:i:s') + { + if (!preg_match('/^[gGhHisuvaA\W]+$/', $format)) { + throw new ComponentException(sprintf('"%s" is not a valid date format', $format)); + } + + $this->format = $format; + $this->sample = date($format, strtotime('23:59:59')); + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + return $this->isDateTime($this->format, (string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Tld.php b/cacme/vendor/workerman/validation/library/Rules/Tld.php new file mode 100644 index 0000000..42ce87e --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Tld.php @@ -0,0 +1,256 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function in_array; +use function is_scalar; +use function mb_strtoupper; + +/** + * Validates whether the input is a top-level domain. + * + * @author Alexandre Gomes Gaigalas + * @author Bogus + * @author Henrique Moody + * @author Paul Karikari + */ +final class Tld extends AbstractRule +{ + /** + * List extracted from https://data.iana.org/TLD/tlds-alpha-by-domain.txt + */ + private const TLD_LIST = [ + 'AAA', 'AARP', 'ABB', 'ABBOTT', 'ABBVIE', 'ABC', 'ABLE', 'ABOGADO', + 'ABUDHABI', 'AC', 'ACADEMY', 'ACCENTURE', 'ACCOUNTANT', 'ACCOUNTANTS', + 'ACO', 'ACTOR', 'AD', 'ADS', 'ADULT', 'AE', 'AEG', 'AERO', 'AETNA', + 'AF', 'AFL', 'AFRICA', 'AG', 'AGAKHAN', 'AGENCY', 'AI', 'AIG', + 'AIRBUS', 'AIRFORCE', 'AIRTEL', 'AKDN', 'AL', 'ALIBABA', 'ALIPAY', + 'ALLFINANZ', 'ALLSTATE', 'ALLY', 'ALSACE', 'ALSTOM', 'AM', 'AMAZON', + 'AMERICANEXPRESS', 'AMERICANFAMILY', 'AMEX', 'AMFAM', 'AMICA', + 'AMSTERDAM', 'ANALYTICS', 'ANDROID', 'ANQUAN', 'ANZ', 'AO', 'AOL', + 'APARTMENTS', 'APP', 'APPLE', 'AQ', 'AQUARELLE', 'AR', 'ARAB', + 'ARAMCO', 'ARCHI', 'ARMY', 'ARPA', 'ART', 'ARTE', 'AS', 'ASDA', 'ASIA', + 'ASSOCIATES', 'AT', 'ATHLETA', 'ATTORNEY', 'AU', 'AUCTION', 'AUDI', + 'AUDIBLE', 'AUDIO', 'AUSPOST', 'AUTHOR', 'AUTO', 'AUTOS', 'AVIANCA', + 'AW', 'AWS', 'AX', 'AXA', 'AZ', 'AZURE', 'BA', 'BABY', 'BAIDU', + 'BANAMEX', 'BANANAREPUBLIC', 'BAND', 'BANK', 'BAR', 'BARCELONA', + 'BARCLAYCARD', 'BARCLAYS', 'BAREFOOT', 'BARGAINS', 'BASEBALL', + 'BASKETBALL', 'BAUHAUS', 'BAYERN', 'BB', 'BBC', 'BBT', 'BBVA', 'BCG', + 'BCN', 'BD', 'BE', 'BEATS', 'BEAUTY', 'BEER', 'BENTLEY', 'BERLIN', + 'BEST', 'BESTBUY', 'BET', 'BF', 'BG', 'BH', 'BHARTI', 'BI', 'BIBLE', + 'BID', 'BIKE', 'BING', 'BINGO', 'BIO', 'BIZ', 'BJ', 'BLACK', + 'BLACKFRIDAY', 'BLOCKBUSTER', 'BLOG', 'BLOOMBERG', 'BLUE', 'BM', 'BMS', + 'BMW', 'BN', 'BNPPARIBAS', 'BO', 'BOATS', 'BOEHRINGER', 'BOFA', 'BOM', + 'BOND', 'BOO', 'BOOK', 'BOOKING', 'BOSCH', 'BOSTIK', 'BOSTON', 'BOT', + 'BOUTIQUE', 'BOX', 'BR', 'BRADESCO', 'BRIDGESTONE', 'BROADWAY', + 'BROKER', 'BROTHER', 'BRUSSELS', 'BS', 'BT', 'BUILD', 'BUILDERS', + 'BUSINESS', 'BUY', 'BUZZ', 'BV', 'BW', 'BY', 'BZ', 'BZH', 'CA', 'CAB', + 'CAFE', 'CAL', 'CALL', 'CALVINKLEIN', 'CAM', 'CAMERA', 'CAMP', 'CANON', + 'CAPETOWN', 'CAPITAL', 'CAPITALONE', 'CAR', 'CARAVAN', 'CARDS', 'CARE', + 'CAREER', 'CAREERS', 'CARS', 'CASA', 'CASE', 'CASH', 'CASINO', 'CAT', + 'CATERING', 'CATHOLIC', 'CBA', 'CBN', 'CBRE', 'CBS', 'CC', 'CD', + 'CENTER', 'CEO', 'CERN', 'CF', 'CFA', 'CFD', 'CG', 'CH', 'CHANEL', + 'CHANNEL', 'CHARITY', 'CHASE', 'CHAT', 'CHEAP', 'CHINTAI', 'CHRISTMAS', + 'CHROME', 'CHURCH', 'CI', 'CIPRIANI', 'CIRCLE', 'CISCO', 'CITADEL', + 'CITI', 'CITIC', 'CITY', 'CITYEATS', 'CK', 'CL', 'CLAIMS', 'CLEANING', + 'CLICK', 'CLINIC', 'CLINIQUE', 'CLOTHING', 'CLOUD', 'CLUB', 'CLUBMED', + 'CM', 'CN', 'CO', 'COACH', 'CODES', 'COFFEE', 'COLLEGE', 'COLOGNE', + 'COM', 'COMCAST', 'COMMBANK', 'COMMUNITY', 'COMPANY', 'COMPARE', + 'COMPUTER', 'COMSEC', 'CONDOS', 'CONSTRUCTION', 'CONSULTING', + 'CONTACT', 'CONTRACTORS', 'COOKING', 'COOKINGCHANNEL', 'COOL', 'COOP', + 'CORSICA', 'COUNTRY', 'COUPON', 'COUPONS', 'COURSES', 'CPA', 'CR', + 'CREDIT', 'CREDITCARD', 'CREDITUNION', 'CRICKET', 'CROWN', 'CRS', + 'CRUISE', 'CRUISES', 'CU', 'CUISINELLA', 'CV', 'CW', 'CX', 'CY', + 'CYMRU', 'CYOU', 'CZ', 'DABUR', 'DAD', 'DANCE', 'DATA', 'DATE', + 'DATING', 'DATSUN', 'DAY', 'DCLK', 'DDS', 'DE', 'DEAL', 'DEALER', + 'DEALS', 'DEGREE', 'DELIVERY', 'DELL', 'DELOITTE', 'DELTA', 'DEMOCRAT', + 'DENTAL', 'DENTIST', 'DESI', 'DESIGN', 'DEV', 'DHL', 'DIAMONDS', + 'DIET', 'DIGITAL', 'DIRECT', 'DIRECTORY', 'DISCOUNT', 'DISCOVER', + 'DISH', 'DIY', 'DJ', 'DK', 'DM', 'DNP', 'DO', 'DOCS', 'DOCTOR', 'DOG', + 'DOMAINS', 'DOT', 'DOWNLOAD', 'DRIVE', 'DTV', 'DUBAI', 'DUNLOP', + 'DUPONT', 'DURBAN', 'DVAG', 'DVR', 'DZ', 'EARTH', 'EAT', 'EC', 'ECO', + 'EDEKA', 'EDU', 'EDUCATION', 'EE', 'EG', 'EMAIL', 'EMERCK', 'ENERGY', + 'ENGINEER', 'ENGINEERING', 'ENTERPRISES', 'EPSON', 'EQUIPMENT', 'ER', + 'ERICSSON', 'ERNI', 'ES', 'ESQ', 'ESTATE', 'ET', 'ETISALAT', 'EU', + 'EUROVISION', 'EUS', 'EVENTS', 'EXCHANGE', 'EXPERT', 'EXPOSED', + 'EXPRESS', 'EXTRASPACE', 'FAGE', 'FAIL', 'FAIRWINDS', 'FAITH', + 'FAMILY', 'FAN', 'FANS', 'FARM', 'FARMERS', 'FASHION', 'FAST', 'FEDEX', + 'FEEDBACK', 'FERRARI', 'FERRERO', 'FI', 'FIDELITY', 'FIDO', 'FILM', + 'FINAL', 'FINANCE', 'FINANCIAL', 'FIRE', 'FIRESTONE', 'FIRMDALE', + 'FISH', 'FISHING', 'FIT', 'FITNESS', 'FJ', 'FK', 'FLICKR', 'FLIGHTS', + 'FLIR', 'FLORIST', 'FLOWERS', 'FLY', 'FM', 'FO', 'FOO', 'FOOD', + 'FOODNETWORK', 'FOOTBALL', 'FORD', 'FOREX', 'FORSALE', 'FORUM', + 'FOUNDATION', 'FOX', 'FR', 'FREE', 'FRESENIUS', 'FRL', 'FROGANS', + 'FRONTDOOR', 'FRONTIER', 'FTR', 'FUJITSU', 'FUN', 'FUND', 'FURNITURE', + 'FUTBOL', 'FYI', 'GA', 'GAL', 'GALLERY', 'GALLO', 'GALLUP', 'GAME', + 'GAMES', 'GAP', 'GARDEN', 'GAY', 'GB', 'GBIZ', 'GD', 'GDN', 'GE', + 'GEA', 'GENT', 'GENTING', 'GEORGE', 'GF', 'GG', 'GGEE', 'GH', 'GI', + 'GIFT', 'GIFTS', 'GIVES', 'GIVING', 'GL', 'GLASS', 'GLE', 'GLOBAL', + 'GLOBO', 'GM', 'GMAIL', 'GMBH', 'GMO', 'GMX', 'GN', 'GODADDY', 'GOLD', + 'GOLDPOINT', 'GOLF', 'GOO', 'GOODYEAR', 'GOOG', 'GOOGLE', 'GOP', 'GOT', + 'GOV', 'GP', 'GQ', 'GR', 'GRAINGER', 'GRAPHICS', 'GRATIS', 'GREEN', + 'GRIPE', 'GROCERY', 'GROUP', 'GS', 'GT', 'GU', 'GUARDIAN', 'GUCCI', + 'GUGE', 'GUIDE', 'GUITARS', 'GURU', 'GW', 'GY', 'HAIR', 'HAMBURG', + 'HANGOUT', 'HAUS', 'HBO', 'HDFC', 'HDFCBANK', 'HEALTH', 'HEALTHCARE', + 'HELP', 'HELSINKI', 'HERE', 'HERMES', 'HGTV', 'HIPHOP', 'HISAMITSU', + 'HITACHI', 'HIV', 'HK', 'HKT', 'HM', 'HN', 'HOCKEY', 'HOLDINGS', + 'HOLIDAY', 'HOMEDEPOT', 'HOMEGOODS', 'HOMES', 'HOMESENSE', 'HONDA', + 'HORSE', 'HOSPITAL', 'HOST', 'HOSTING', 'HOT', 'HOTELES', 'HOTELS', + 'HOTMAIL', 'HOUSE', 'HOW', 'HR', 'HSBC', 'HT', 'HU', 'HUGHES', 'HYATT', + 'HYUNDAI', 'IBM', 'ICBC', 'ICE', 'ICU', 'ID', 'IE', 'IEEE', 'IFM', + 'IKANO', 'IL', 'IM', 'IMAMAT', 'IMDB', 'IMMO', 'IMMOBILIEN', 'IN', + 'INC', 'INDUSTRIES', 'INFINITI', 'INFO', 'ING', 'INK', 'INSTITUTE', + 'INSURANCE', 'INSURE', 'INT', 'INTERNATIONAL', 'INTUIT', 'INVESTMENTS', + 'IO', 'IPIRANGA', 'IQ', 'IR', 'IRISH', 'IS', 'ISMAILI', 'IST', + 'ISTANBUL', 'IT', 'ITAU', 'ITV', 'JAGUAR', 'JAVA', 'JCB', 'JE', 'JEEP', + 'JETZT', 'JEWELRY', 'JIO', 'JLL', 'JM', 'JMP', 'JNJ', 'JO', 'JOBS', + 'JOBURG', 'JOT', 'JOY', 'JP', 'JPMORGAN', 'JPRS', 'JUEGOS', 'JUNIPER', + 'KAUFEN', 'KDDI', 'KE', 'KERRYHOTELS', 'KERRYLOGISTICS', + 'KERRYPROPERTIES', 'KFH', 'KG', 'KH', 'KI', 'KIA', 'KIDS', 'KIM', + 'KINDER', 'KINDLE', 'KITCHEN', 'KIWI', 'KM', 'KN', 'KOELN', 'KOMATSU', + 'KOSHER', 'KP', 'KPMG', 'KPN', 'KR', 'KRD', 'KRED', 'KUOKGROUP', 'KW', + 'KY', 'KYOTO', 'KZ', 'LA', 'LACAIXA', 'LAMBORGHINI', 'LAMER', + 'LANCASTER', 'LAND', 'LANDROVER', 'LANXESS', 'LASALLE', 'LAT', + 'LATINO', 'LATROBE', 'LAW', 'LAWYER', 'LB', 'LC', 'LDS', 'LEASE', + 'LECLERC', 'LEFRAK', 'LEGAL', 'LEGO', 'LEXUS', 'LGBT', 'LI', 'LIDL', + 'LIFE', 'LIFEINSURANCE', 'LIFESTYLE', 'LIGHTING', 'LIKE', 'LILLY', + 'LIMITED', 'LIMO', 'LINCOLN', 'LINK', 'LIPSY', 'LIVE', 'LIVING', 'LK', + 'LLC', 'LLP', 'LOAN', 'LOANS', 'LOCKER', 'LOCUS', 'LOL', 'LONDON', + 'LOTTE', 'LOTTO', 'LOVE', 'LPL', 'LPLFINANCIAL', 'LR', 'LS', 'LT', + 'LTD', 'LTDA', 'LU', 'LUNDBECK', 'LUXE', 'LUXURY', 'LV', 'LY', 'MA', + 'MADRID', 'MAIF', 'MAISON', 'MAKEUP', 'MAN', 'MANAGEMENT', 'MANGO', + 'MAP', 'MARKET', 'MARKETING', 'MARKETS', 'MARRIOTT', 'MARSHALLS', + 'MATTEL', 'MBA', 'MC', 'MCKINSEY', 'MD', 'ME', 'MED', 'MEDIA', 'MEET', + 'MELBOURNE', 'MEME', 'MEMORIAL', 'MEN', 'MENU', 'MERCKMSD', 'MG', 'MH', + 'MIAMI', 'MICROSOFT', 'MIL', 'MINI', 'MINT', 'MIT', 'MITSUBISHI', 'MK', + 'ML', 'MLB', 'MLS', 'MM', 'MMA', 'MN', 'MO', 'MOBI', 'MOBILE', 'MODA', + 'MOE', 'MOI', 'MOM', 'MONASH', 'MONEY', 'MONSTER', 'MORMON', + 'MORTGAGE', 'MOSCOW', 'MOTO', 'MOTORCYCLES', 'MOV', 'MOVIE', 'MP', + 'MQ', 'MR', 'MS', 'MSD', 'MT', 'MTN', 'MTR', 'MU', 'MUSEUM', 'MUSIC', + 'MUTUAL', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NAB', 'NAGOYA', 'NAME', + 'NATURA', 'NAVY', 'NBA', 'NC', 'NE', 'NEC', 'NET', 'NETBANK', + 'NETFLIX', 'NETWORK', 'NEUSTAR', 'NEW', 'NEWS', 'NEXT', 'NEXTDIRECT', + 'NEXUS', 'NF', 'NFL', 'NG', 'NGO', 'NHK', 'NI', 'NICO', 'NIKE', + 'NIKON', 'NINJA', 'NISSAN', 'NISSAY', 'NL', 'NO', 'NOKIA', + 'NORTHWESTERNMUTUAL', 'NORTON', 'NOW', 'NOWRUZ', 'NOWTV', 'NP', 'NR', + 'NRA', 'NRW', 'NTT', 'NU', 'NYC', 'NZ', 'OBI', 'OBSERVER', 'OFFICE', + 'OKINAWA', 'OLAYAN', 'OLAYANGROUP', 'OLDNAVY', 'OLLO', 'OM', 'OMEGA', + 'ONE', 'ONG', 'ONL', 'ONLINE', 'OOO', 'OPEN', 'ORACLE', 'ORANGE', + 'ORG', 'ORGANIC', 'ORIGINS', 'OSAKA', 'OTSUKA', 'OTT', 'OVH', 'PA', + 'PAGE', 'PANASONIC', 'PARIS', 'PARS', 'PARTNERS', 'PARTS', 'PARTY', + 'PASSAGENS', 'PAY', 'PCCW', 'PE', 'PET', 'PF', 'PFIZER', 'PG', 'PH', + 'PHARMACY', 'PHD', 'PHILIPS', 'PHONE', 'PHOTO', 'PHOTOGRAPHY', + 'PHOTOS', 'PHYSIO', 'PICS', 'PICTET', 'PICTURES', 'PID', 'PIN', 'PING', + 'PINK', 'PIONEER', 'PIZZA', 'PK', 'PL', 'PLACE', 'PLAY', 'PLAYSTATION', + 'PLUMBING', 'PLUS', 'PM', 'PN', 'PNC', 'POHL', 'POKER', 'POLITIE', + 'PORN', 'POST', 'PR', 'PRAMERICA', 'PRAXI', 'PRESS', 'PRIME', 'PRO', + 'PROD', 'PRODUCTIONS', 'PROF', 'PROGRESSIVE', 'PROMO', 'PROPERTIES', + 'PROPERTY', 'PROTECTION', 'PRU', 'PRUDENTIAL', 'PS', 'PT', 'PUB', 'PW', + 'PWC', 'PY', 'QA', 'QPON', 'QUEBEC', 'QUEST', 'RACING', 'RADIO', 'RE', + 'READ', 'REALESTATE', 'REALTOR', 'REALTY', 'RECIPES', 'RED', + 'REDSTONE', 'REDUMBRELLA', 'REHAB', 'REISE', 'REISEN', 'REIT', + 'RELIANCE', 'REN', 'RENT', 'RENTALS', 'REPAIR', 'REPORT', 'REPUBLICAN', + 'REST', 'RESTAURANT', 'REVIEW', 'REVIEWS', 'REXROTH', 'RICH', + 'RICHARDLI', 'RICOH', 'RIL', 'RIO', 'RIP', 'RO', 'ROCHER', 'ROCKS', + 'RODEO', 'ROGERS', 'ROOM', 'RS', 'RSVP', 'RU', 'RUGBY', 'RUHR', 'RUN', + 'RW', 'RWE', 'RYUKYU', 'SA', 'SAARLAND', 'SAFE', 'SAFETY', 'SAKURA', + 'SALE', 'SALON', 'SAMSCLUB', 'SAMSUNG', 'SANDVIK', 'SANDVIKCOROMANT', + 'SANOFI', 'SAP', 'SARL', 'SAS', 'SAVE', 'SAXO', 'SB', 'SBI', 'SBS', + 'SC', 'SCA', 'SCB', 'SCHAEFFLER', 'SCHMIDT', 'SCHOLARSHIPS', 'SCHOOL', + 'SCHULE', 'SCHWARZ', 'SCIENCE', 'SCOT', 'SD', 'SE', 'SEARCH', 'SEAT', + 'SECURE', 'SECURITY', 'SEEK', 'SELECT', 'SENER', 'SERVICES', 'SEVEN', + 'SEW', 'SEX', 'SEXY', 'SFR', 'SG', 'SH', 'SHANGRILA', 'SHARP', 'SHAW', + 'SHELL', 'SHIA', 'SHIKSHA', 'SHOES', 'SHOP', 'SHOPPING', 'SHOUJI', + 'SHOW', 'SHOWTIME', 'SI', 'SILK', 'SINA', 'SINGLES', 'SITE', 'SJ', + 'SK', 'SKI', 'SKIN', 'SKY', 'SKYPE', 'SL', 'SLING', 'SM', 'SMART', + 'SMILE', 'SN', 'SNCF', 'SO', 'SOCCER', 'SOCIAL', 'SOFTBANK', + 'SOFTWARE', 'SOHU', 'SOLAR', 'SOLUTIONS', 'SONG', 'SONY', 'SOY', 'SPA', + 'SPACE', 'SPORT', 'SPOT', 'SR', 'SRL', 'SS', 'ST', 'STADA', 'STAPLES', + 'STAR', 'STATEBANK', 'STATEFARM', 'STC', 'STCGROUP', 'STOCKHOLM', + 'STORAGE', 'STORE', 'STREAM', 'STUDIO', 'STUDY', 'STYLE', 'SU', + 'SUCKS', 'SUPPLIES', 'SUPPLY', 'SUPPORT', 'SURF', 'SURGERY', 'SUZUKI', + 'SV', 'SWATCH', 'SWISS', 'SX', 'SY', 'SYDNEY', 'SYSTEMS', 'SZ', 'TAB', + 'TAIPEI', 'TALK', 'TAOBAO', 'TARGET', 'TATAMOTORS', 'TATAR', 'TATTOO', + 'TAX', 'TAXI', 'TC', 'TCI', 'TD', 'TDK', 'TEAM', 'TECH', 'TECHNOLOGY', + 'TEL', 'TEMASEK', 'TENNIS', 'TEVA', 'TF', 'TG', 'TH', 'THD', 'THEATER', + 'THEATRE', 'TIAA', 'TICKETS', 'TIENDA', 'TIFFANY', 'TIPS', 'TIRES', + 'TIROL', 'TJ', 'TJMAXX', 'TJX', 'TK', 'TKMAXX', 'TL', 'TM', 'TMALL', + 'TN', 'TO', 'TODAY', 'TOKYO', 'TOOLS', 'TOP', 'TORAY', 'TOSHIBA', + 'TOTAL', 'TOURS', 'TOWN', 'TOYOTA', 'TOYS', 'TR', 'TRADE', 'TRADING', + 'TRAINING', 'TRAVEL', 'TRAVELCHANNEL', 'TRAVELERS', + 'TRAVELERSINSURANCE', 'TRUST', 'TRV', 'TT', 'TUBE', 'TUI', 'TUNES', + 'TUSHU', 'TV', 'TVS', 'TW', 'TZ', 'UA', 'UBANK', 'UBS', 'UG', 'UK', + 'UNICOM', 'UNIVERSITY', 'UNO', 'UOL', 'UPS', 'US', 'UY', 'UZ', 'VA', + 'VACATIONS', 'VANA', 'VANGUARD', 'VC', 'VE', 'VEGAS', 'VENTURES', + 'VERISIGN', 'VERSICHERUNG', 'VET', 'VG', 'VI', 'VIAJES', 'VIDEO', + 'VIG', 'VIKING', 'VILLAS', 'VIN', 'VIP', 'VIRGIN', 'VISA', 'VISION', + 'VIVA', 'VIVO', 'VLAANDEREN', 'VN', 'VODKA', 'VOLKSWAGEN', 'VOLVO', + 'VOTE', 'VOTING', 'VOTO', 'VOYAGE', 'VU', 'VUELOS', 'WALES', 'WALMART', + 'WALTER', 'WANG', 'WANGGOU', 'WATCH', 'WATCHES', 'WEATHER', + 'WEATHERCHANNEL', 'WEBCAM', 'WEBER', 'WEBSITE', 'WED', 'WEDDING', + 'WEIBO', 'WEIR', 'WF', 'WHOSWHO', 'WIEN', 'WIKI', 'WILLIAMHILL', 'WIN', + 'WINDOWS', 'WINE', 'WINNERS', 'WME', 'WOLTERSKLUWER', 'WOODSIDE', + 'WORK', 'WORKS', 'WORLD', 'WOW', 'WS', 'WTC', 'WTF', 'XBOX', 'XEROX', + 'XFINITY', 'XIHUAN', 'XIN', 'XN--11B4C3D', 'XN--1CK2E1B', + 'XN--1QQW23A', 'XN--2SCRJ9C', 'XN--30RR7Y', 'XN--3BST00M', + 'XN--3DS443G', 'XN--3E0B707E', 'XN--3HCRJ9C', 'XN--3PXU8K', + 'XN--42C2D9A', 'XN--45BR5CYL', 'XN--45BRJ9C', 'XN--45Q11C', + 'XN--4DBRK0CE', 'XN--4GBRIM', 'XN--54B7FTA0CC', 'XN--55QW42G', + 'XN--55QX5D', 'XN--5SU34J936BGSG', 'XN--5TZM5G', 'XN--6FRZ82G', + 'XN--6QQ986B3XL', 'XN--80ADXHKS', 'XN--80AO21A', 'XN--80AQECDR1A', + 'XN--80ASEHDB', 'XN--80ASWG', 'XN--8Y0A063A', 'XN--90A3AC', 'XN--90AE', + 'XN--90AIS', 'XN--9DBQ2A', 'XN--9ET52U', 'XN--9KRT00A', + 'XN--B4W605FERD', 'XN--BCK1B9A5DRE4C', 'XN--C1AVG', 'XN--C2BR7G', + 'XN--CCK2B3B', 'XN--CCKWCXETD', 'XN--CG4BKI', 'XN--CLCHC0EA0B2G2A9GCD', + 'XN--CZR694B', 'XN--CZRS0T', 'XN--CZRU2D', 'XN--D1ACJ3B', 'XN--D1ALF', + 'XN--E1A4C', 'XN--ECKVDTC9D', 'XN--EFVY88H', 'XN--FCT429K', + 'XN--FHBEI', 'XN--FIQ228C5HS', 'XN--FIQ64B', 'XN--FIQS8S', + 'XN--FIQZ9S', 'XN--FJQ720A', 'XN--FLW351E', 'XN--FPCRJ9C3D', + 'XN--FZC2C9E2C', 'XN--FZYS8D69UVGM', 'XN--G2XX48C', 'XN--GCKR3F0F', + 'XN--GECRJ9C', 'XN--GK3AT1E', 'XN--H2BREG3EVE', 'XN--H2BRJ9C', + 'XN--H2BRJ9C8C', 'XN--HXT814E', 'XN--I1B6B1A6A2E', 'XN--IMR513N', + 'XN--IO0A7I', 'XN--J1AEF', 'XN--J1AMH', 'XN--J6W193G', + 'XN--JLQ480N2RG', 'XN--JVR189M', 'XN--KCRX77D1X4A', 'XN--KPRW13D', + 'XN--KPRY57D', 'XN--KPUT3I', 'XN--L1ACC', 'XN--LGBBAT1AD8J', + 'XN--MGB9AWBF', 'XN--MGBA3A3EJT', 'XN--MGBA3A4F16A', + 'XN--MGBA7C0BBN0A', 'XN--MGBAAKC7DVF', 'XN--MGBAAM7A8H', + 'XN--MGBAB2BD', 'XN--MGBAH1A3HJKRD', 'XN--MGBAI9AZGQP6J', + 'XN--MGBAYH7GPA', 'XN--MGBBH1A', 'XN--MGBBH1A71E', 'XN--MGBC0A9AZCG', + 'XN--MGBCA7DZDO', 'XN--MGBCPQ6GPA1A', 'XN--MGBERP4A5D4AR', + 'XN--MGBGU82A', 'XN--MGBI4ECEXP', 'XN--MGBPL2FH', 'XN--MGBT3DHD', + 'XN--MGBTX2B', 'XN--MGBX4CD0AB', 'XN--MIX891F', 'XN--MK1BU44C', + 'XN--MXTQ1M', 'XN--NGBC5AZD', 'XN--NGBE9E0A', 'XN--NGBRX', 'XN--NODE', + 'XN--NQV7F', 'XN--NQV7FS00EMA', 'XN--NYQY26A', 'XN--O3CW4H', + 'XN--OGBPF8FL', 'XN--OTU796D', 'XN--P1ACF', 'XN--P1AI', 'XN--PGBS0DH', + 'XN--PSSY2U', 'XN--Q7CE6A', 'XN--Q9JYB4C', 'XN--QCKA1PMC', 'XN--QXA6A', + 'XN--QXAM', 'XN--RHQV96G', 'XN--ROVU88B', 'XN--RVC1E0AM3E', + 'XN--S9BRJ9C', 'XN--SES554G', 'XN--T60B56A', 'XN--TCKWE', + 'XN--TIQ49XQYJ', 'XN--UNUP4Y', 'XN--VERMGENSBERATER-CTB', + 'XN--VERMGENSBERATUNG-PWB', 'XN--VHQUV', 'XN--VUQ861B', + 'XN--W4R85EL8FHU5DNRA', 'XN--W4RS40L', 'XN--WGBH1C', 'XN--WGBL6A', + 'XN--XHQ521B', 'XN--XKC2AL3HYE2A', 'XN--XKC2DL3A5EE0H', 'XN--Y9A3AQ', + 'XN--YFRO4I67O', 'XN--YGBI2AMMX', 'XN--ZFR164B', 'XXX', 'XYZ', + 'YACHTS', 'YAHOO', 'YAMAXUN', 'YANDEX', 'YE', 'YODOBASHI', 'YOGA', + 'YOKOHAMA', 'YOU', 'YOUTUBE', 'YT', 'YUN', 'ZA', 'ZAPPOS', 'ZARA', + 'ZERO', 'ZIP', 'ZM', 'ZONE', 'ZUERICH', 'ZW', + ]; + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_scalar($input)) { + return false; + } + + return in_array(mb_strtoupper((string) $input), self::TLD_LIST); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/TrueVal.php b/cacme/vendor/workerman/validation/library/Rules/TrueVal.php new file mode 100644 index 0000000..c9018e2 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/TrueVal.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function filter_var; + +use const FILTER_NULL_ON_FAILURE; +use const FILTER_VALIDATE_BOOLEAN; + +/** + * Validates if a value is considered as true. + * + * @author Henrique Moody + * @author Paul Karikari + */ +final class TrueVal extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + return filter_var($input, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) === true; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Type.php b/cacme/vendor/workerman/validation/library/Rules/Type.php new file mode 100644 index 0000000..f16d80a --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Type.php @@ -0,0 +1,86 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_keys; +use function gettype; +use function implode; +use function is_callable; +use function sprintf; + +/** + * Validates the type of input. + * + * @author Gabriel Caruso + * @author Henrique Moody + * @author Paul Karikari + */ +final class Type extends AbstractRule +{ + /** + * Collection of available types for validation. + * + */ + private const AVAILABLE_TYPES = [ + 'array' => 'array', + 'bool' => 'boolean', + 'boolean' => 'boolean', + 'callable' => 'callable', + 'double' => 'double', + 'float' => 'double', + 'int' => 'integer', + 'integer' => 'integer', + 'null' => 'NULL', + 'object' => 'object', + 'resource' => 'resource', + 'string' => 'string', + ]; + + /** + * Type to validate input against. + * + * @var string + */ + private $type; + + /** + * Initializes the rule. + * + * @throws ComponentException When $type is not a valid one + */ + public function __construct(string $type) + { + if (!isset(self::AVAILABLE_TYPES[$type])) { + throw new ComponentException( + sprintf( + '"%s" is not a valid type (Available: %s)', + $type, + implode(', ', array_keys(self::AVAILABLE_TYPES)) + ) + ); + } + + $this->type = $type; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->type === 'callable') { + return is_callable($input); + } + + return self::AVAILABLE_TYPES[$this->type] === gettype($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Unique.php b/cacme/vendor/workerman/validation/library/Rules/Unique.php new file mode 100644 index 0000000..2ce865c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Unique.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function array_unique; +use function is_array; + +use const SORT_REGULAR; + +/** + * Validates whether the input array contains only unique values. + * + * @author Henrique Moody + * @author Krzysztof Śmiałek + * @author Paul Karikari + */ +final class Unique extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_array($input)) { + return false; + } + + return $input == array_unique($input, SORT_REGULAR); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Uploaded.php b/cacme/vendor/workerman/validation/library/Rules/Uploaded.php new file mode 100644 index 0000000..9bc7eda --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Uploaded.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Psr\Http\Message\UploadedFileInterface; +use SplFileInfo; + +use function is_scalar; +use function is_uploaded_file; + +/** + * Validates if the given data is a file that was uploaded via HTTP POST. + * + * @author Henrique Moody + * @author Paul Karikari + */ +final class Uploaded extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $this->validate($input->getPathname()); + } + + if ($input instanceof UploadedFileInterface) { + return true; + } + + if (!is_scalar($input)) { + return false; + } + + return is_uploaded_file((string) $input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Uppercase.php b/cacme/vendor/workerman/validation/library/Rules/Uppercase.php new file mode 100644 index 0000000..58ae4e0 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Uppercase.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function mb_strtoupper; + +/** + * Validates whether the characters in the input are uppercase. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Benevides + * @author Henrique Moody + * @author Jean Pimentel + */ +final class Uppercase extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return $input === mb_strtoupper($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Url.php b/cacme/vendor/workerman/validation/library/Rules/Url.php new file mode 100644 index 0000000..f1775b3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Url.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use const FILTER_VALIDATE_URL; + +/** + * Validates whether the input is a URL. + * + * @author Henrique Moody + */ +final class Url extends AbstractEnvelope +{ + /** + * Initializes the rule. + * + * @throws ComponentException + */ + public function __construct() + { + parent::__construct(new FilterVar(FILTER_VALIDATE_URL)); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Uuid.php b/cacme/vendor/workerman/validation/library/Rules/Uuid.php new file mode 100644 index 0000000..1ea7659 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Uuid.php @@ -0,0 +1,80 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function is_string; +use function preg_match; +use function sprintf; + +/** + * Validates whether the input is a valid UUID. + * + * It also supports validation of specific versions 1, 3, 4 and 5. + * + * @author Dick van der Heiden + * @author Henrique Moody + * @author Michael Weimann + */ +final class Uuid extends AbstractRule +{ + /** + * Placeholder in "sprintf()" format used to create the REGEX that validates inputs. + */ + private const PATTERN_FORMAT = '/^[0-9a-f]{8}-[0-9a-f]{4}-%s[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i'; + + /** + * The UUID version to validate for. + * + * @var int|null + */ + private $version; + + /** + * Initializes the rule with the desired version. + * + * @throws ComponentException when the version is not valid + */ + public function __construct(?int $version = null) + { + if ($version !== null && !$this->isSupportedVersion($version)) { + throw new ComponentException(sprintf('Only versions 1, 3, 4, and 5 are supported: %d given', $version)); + } + + $this->version = $version; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return preg_match($this->getPattern(), $input) > 0; + } + + private function isSupportedVersion(int $version): bool + { + return $version >= 1 && $version <= 5 && $version !== 2; + } + + private function getPattern(): string + { + if ($this->version !== null) { + return sprintf(self::PATTERN_FORMAT, $this->version); + } + + return sprintf(self::PATTERN_FORMAT, '[13-5]'); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Version.php b/cacme/vendor/workerman/validation/library/Rules/Version.php new file mode 100644 index 0000000..6dfb0cf --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Version.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function preg_match; + +/** + * Validates version numbers using Semantic Versioning. + * + * @see http://semver.org/ + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class Version extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return preg_match('/^[0-9]+\.[0-9]+\.[0-9]+([+-][^+-][0-9A-Za-z-.]*)?$/', $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/VideoUrl.php b/cacme/vendor/workerman/validation/library/Rules/VideoUrl.php new file mode 100644 index 0000000..7ba7d3c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/VideoUrl.php @@ -0,0 +1,90 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +use function array_keys; +use function is_string; +use function mb_strtolower; +use function preg_match; +use function sprintf; + +/** + * Validates if the input is a video URL value. + * + * @author Danilo Correa + * @author Emmerson Siqueira + * @author Henrique Moody + * @author Ricardo Gobbo + */ +final class VideoUrl extends AbstractRule +{ + private const SERVICES = [ + // phpcs:disable Generic.Files.LineLength.TooLong + 'youtube' => '@^https?://(www\.)?(?:youtube\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^\"&?/]{11})@i', + 'vimeo' => '@^https?://(www\.)?(player\.)?(vimeo\.com/)((channels/[A-z]+/)|(groups/[A-z]+/videos/)|(video/))?([0-9]+)@i', + 'twitch' => '@^https?://(((www\.)?twitch\.tv/videos/[0-9]+)|clips\.twitch\.tv/[a-zA-Z]+)$@i', + // phpcs:enable Generic.Files.LineLength.TooLong + ]; + + /** + * @var string|null + */ + private $service; + + /** + * Create a new instance VideoUrl. + * + * @throws ComponentException when the given service is not supported + */ + public function __construct(?string $service = null) + { + if ($service !== null && !$this->isSupportedService($service)) { + throw new ComponentException(sprintf('"%s" is not a recognized video service.', $service)); + } + + $this->service = $service; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + if ($this->service !== null) { + return $this->isValid($this->service, $input); + } + + foreach (array_keys(self::SERVICES) as $service) { + if (!$this->isValid($service, $input)) { + continue; + } + + return true; + } + + return false; + } + + private function isSupportedService(string $service): bool + { + return isset(self::SERVICES[mb_strtolower($service)]); + } + + private function isValid(string $service, string $input): bool + { + return preg_match(self::SERVICES[mb_strtolower($service)], $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Vowel.php b/cacme/vendor/workerman/validation/library/Rules/Vowel.php new file mode 100644 index 0000000..e0988fa --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Vowel.php @@ -0,0 +1,29 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function preg_match; + +/** + * Validates whether the input contains only vowels. + * + * @author Henrique Moody + * @author Nick Lombard + */ +final class Vowel extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return preg_match('/^[aeiouAEIOU]+$/', $input) > 0; + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/When.php b/cacme/vendor/workerman/validation/library/Rules/When.php new file mode 100644 index 0000000..292b47b --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/When.php @@ -0,0 +1,91 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\AlwaysInvalidException; +use Respect\Validation\Validatable; + +/** + * A ternary validator that accepts three parameters. + * + * @author Alexandre Gomes Gaigalas + * @author Danilo Correa + * @author Henrique Moody + * @author Hugo Hamon + */ +final class When extends AbstractRule +{ + /** + * @var Validatable + */ + private $when; + + /** + * @var Validatable + */ + private $then; + + /** + * @var Validatable + */ + private $else; + + public function __construct(Validatable $when, Validatable $then, ?Validatable $else = null) + { + $this->when = $when; + $this->then = $then; + if ($else === null) { + $else = new AlwaysInvalid(); + $else->setTemplate(AlwaysInvalidException::SIMPLE); + } + + $this->else = $else; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($this->when->validate($input)) { + return $this->then->validate($input); + } + + return $this->else->validate($input); + } + + /** + * {@inheritDoc} + */ + public function assert($input): void + { + if ($this->when->validate($input)) { + $this->then->assert($input); + + return; + } + + $this->else->assert($input); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + if ($this->when->validate($input)) { + $this->then->check($input); + + return; + } + + $this->else->check($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Writable.php b/cacme/vendor/workerman/validation/library/Rules/Writable.php new file mode 100644 index 0000000..7b87a8c --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Writable.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use Psr\Http\Message\StreamInterface; +use SplFileInfo; + +use function is_string; +use function is_writable; + +/** + * Validates if the given input is writable file. + * + * @author Danilo Correa + * @author Henrique Moody + */ +final class Writable extends AbstractRule +{ + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if ($input instanceof SplFileInfo) { + return $input->isWritable(); + } + + if ($input instanceof StreamInterface) { + return $input->isWritable(); + } + + return is_string($input) && is_writable($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Xdigit.php b/cacme/vendor/workerman/validation/library/Rules/Xdigit.php new file mode 100644 index 0000000..4322d6d --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Xdigit.php @@ -0,0 +1,27 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function ctype_xdigit; + +/** + * @author Andre Ramaciotti + * @author Henrique Moody + */ +final class Xdigit extends AbstractFilterRule +{ + /** + * {@inheritDoc} + */ + protected function validateFilteredInput(string $input): bool + { + return ctype_xdigit($input); + } +} diff --git a/cacme/vendor/workerman/validation/library/Rules/Yes.php b/cacme/vendor/workerman/validation/library/Rules/Yes.php new file mode 100644 index 0000000..fc8b27f --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Rules/Yes.php @@ -0,0 +1,59 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Rules; + +use function is_string; +use function nl_langinfo; +use function preg_match; + +use const YESEXPR; + +/** + * Validates if the input considered as "Yes". + * + * @author Cameron Hall + * @author Henrique Moody + */ +final class Yes extends AbstractRule +{ + /** + * @var bool + */ + private $useLocale; + + /** + * Initializes the rule. + */ + public function __construct(bool $useLocale = false) + { + $this->useLocale = $useLocale; + } + + /** + * {@inheritDoc} + */ + public function validate($input): bool + { + if (!is_string($input)) { + return false; + } + + return preg_match($this->getPattern(), $input) > 0; + } + + private function getPattern(): string + { + if ($this->useLocale) { + return '/' . nl_langinfo(YESEXPR) . '/'; + } + + return '/^y(eah?|ep|es)?$/i'; + } +} diff --git a/cacme/vendor/workerman/validation/library/StaticValidator.php b/cacme/vendor/workerman/validation/library/StaticValidator.php new file mode 100644 index 0000000..9f2fee3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/StaticValidator.php @@ -0,0 +1,375 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation; + +use finfo; +use Respect\Validation\Rules\Key; + +interface StaticValidator +{ + public static function allOf(Validatable ...$rule): ChainedValidator; + + public static function alnum(string ...$additionalChars): ChainedValidator; + + public static function alpha(string ...$additionalChars): ChainedValidator; + + public static function alwaysInvalid(): ChainedValidator; + + public static function alwaysValid(): ChainedValidator; + + public static function anyOf(Validatable ...$rule): ChainedValidator; + + public static function arrayType(): ChainedValidator; + + public static function arrayVal(): ChainedValidator; + + public static function attribute( + string $reference, + ?Validatable $validator = null, + bool $mandatory = true + ): ChainedValidator; + + public static function base(int $base, ?string $chars = null): ChainedValidator; + + public static function base64(): ChainedValidator; + + /** + * @param mixed $minimum + * @param mixed $maximum + */ + public static function between($minimum, $maximum): ChainedValidator; + + public static function bic(string $countryCode): ChainedValidator; + + public static function boolType(): ChainedValidator; + + public static function boolVal(): ChainedValidator; + + public static function bsn(): ChainedValidator; + + public static function call(callable $callable, Validatable $rule): ChainedValidator; + + public static function callableType(): ChainedValidator; + + public static function callback(callable $callback): ChainedValidator; + + public static function charset(string ...$charset): ChainedValidator; + + public static function cnh(): ChainedValidator; + + public static function cnpj(): ChainedValidator; + + public static function control(string ...$additionalChars): ChainedValidator; + + public static function consonant(string ...$additionalChars): ChainedValidator; + + /** + * @param mixed $containsValue + */ + public static function contains($containsValue, bool $identical = false): ChainedValidator; + + /** + * @param mixed[] $needles + */ + public static function containsAny(array $needles, bool $strictCompareArray = false): ChainedValidator; + + public static function countable(): ChainedValidator; + + public static function countryCode(?string $set = null): ChainedValidator; + + public static function currencyCode(): ChainedValidator; + + public static function cpf(): ChainedValidator; + + public static function creditCard(?string $brand = null): ChainedValidator; + + public static function date(string $format = 'Y-m-d'): ChainedValidator; + + public static function dateTime(?string $format = null): ChainedValidator; + + public static function decimal(int $decimals): ChainedValidator; + + public static function digit(string ...$additionalChars): ChainedValidator; + + public static function directory(): ChainedValidator; + + public static function domain(bool $tldCheck = true): ChainedValidator; + + public static function each(Validatable $rule): ChainedValidator; + + public static function email(): ChainedValidator; + + /** + * @param mixed $endValue + */ + public static function endsWith($endValue, bool $identical = false): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function equals($compareTo): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function equivalent($compareTo): ChainedValidator; + + public static function even(): ChainedValidator; + + public static function executable(): ChainedValidator; + + public static function exists(): ChainedValidator; + + public static function extension(string $extension): ChainedValidator; + + public static function factor(int $dividend): ChainedValidator; + + public static function falseVal(): ChainedValidator; + + public static function fibonacci(): ChainedValidator; + + public static function file(): ChainedValidator; + + /** + * @param mixed[]|int $options + */ + public static function filterVar(int $filter, $options = null): ChainedValidator; + + public static function finite(): ChainedValidator; + + public static function floatVal(): ChainedValidator; + + public static function floatType(): ChainedValidator; + + public static function graph(string ...$additionalChars): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function greaterThan($compareTo): ChainedValidator; + + public static function hexRgbColor(): ChainedValidator; + + public static function iban(): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function identical($compareTo): ChainedValidator; + + public static function image(?finfo $fileInfo = null): ChainedValidator; + + public static function imei(): ChainedValidator; + + /** + * @param mixed[]|mixed $haystack + */ + public static function in($haystack, bool $compareIdentical = false): ChainedValidator; + + public static function infinite(): ChainedValidator; + + public static function instance(string $instanceName): ChainedValidator; + + public static function intVal(): ChainedValidator; + + public static function intType(): ChainedValidator; + + public static function ip(string $range = '*', ?int $options = null): ChainedValidator; + + public static function isbn(): ChainedValidator; + + public static function iterableType(): ChainedValidator; + + public static function json(): ChainedValidator; + + public static function key( + string $reference, + ?Validatable $referenceValidator = null, + bool $mandatory = true + ): ChainedValidator; + + public static function keyNested( + string $reference, + ?Validatable $referenceValidator = null, + bool $mandatory = true + ): ChainedValidator; + + public static function keySet(Key ...$rule): ChainedValidator; + + public static function keyValue(string $comparedKey, string $ruleName, string $baseKey): ChainedValidator; + + public static function languageCode(?string $set = null): ChainedValidator; + + public static function leapDate(string $format): ChainedValidator; + + public static function leapYear(): ChainedValidator; + + public static function length(?int $min = null, ?int $max = null, bool $inclusive = true): ChainedValidator; + + public static function lowercase(): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function lessThan($compareTo): ChainedValidator; + + public static function luhn(): ChainedValidator; + + public static function macAddress(): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function max($compareTo): ChainedValidator; + + public static function maxAge(int $age, ?string $format = null): ChainedValidator; + + public static function mimetype(string $mimetype): ChainedValidator; + + /** + * @param mixed $compareTo + */ + public static function min($compareTo): ChainedValidator; + + public static function minAge(int $age, ?string $format = null): ChainedValidator; + + public static function multiple(int $multipleOf): ChainedValidator; + + public static function negative(): ChainedValidator; + + public static function nfeAccessKey(): ChainedValidator; + + public static function nif(): ChainedValidator; + + public static function nip(): ChainedValidator; + + public static function no(bool $useLocale = false): ChainedValidator; + + public static function noneOf(Validatable ...$rule): ChainedValidator; + + public static function not(Validatable $rule): ChainedValidator; + + public static function notBlank(): ChainedValidator; + + public static function notEmoji(): ChainedValidator; + + public static function notEmpty(): ChainedValidator; + + public static function notOptional(): ChainedValidator; + + public static function noWhitespace(): ChainedValidator; + + public static function nullable(Validatable $rule): ChainedValidator; + + public static function nullType(): ChainedValidator; + + public static function number(): ChainedValidator; + + public static function numericVal(): ChainedValidator; + + public static function objectType(): ChainedValidator; + + public static function odd(): ChainedValidator; + + public static function oneOf(Validatable ...$rule): ChainedValidator; + + public static function optional(Validatable $rule): ChainedValidator; + + public static function perfectSquare(): ChainedValidator; + + public static function pesel(): ChainedValidator; + + public static function phone(): ChainedValidator; + + public static function mobile(): ChainedValidator; + public static function phpLabel(): ChainedValidator; + + public static function pis(): ChainedValidator; + + public static function polishIdCard(): ChainedValidator; + + public static function positive(): ChainedValidator; + + public static function postalCode(string $countryCode): ChainedValidator; + + public static function primeNumber(): ChainedValidator; + + public static function printable(string ...$additionalChars): ChainedValidator; + + public static function punct(string ...$additionalChars): ChainedValidator; + + public static function readable(): ChainedValidator; + + public static function regex(string $regex): ChainedValidator; + + public static function resourceType(): ChainedValidator; + + public static function roman(): ChainedValidator; + + public static function scalarVal(): ChainedValidator; + + public static function size(?string $minSize = null, ?string $maxSize = null): ChainedValidator; + + public static function slug(): ChainedValidator; + + public static function sorted(string $direction): ChainedValidator; + + public static function space(string ...$additionalChars): ChainedValidator; + + /** + * @param mixed $startValue + */ + public static function startsWith($startValue, bool $identical = false): ChainedValidator; + + public static function stringType(): ChainedValidator; + + public static function stringVal(): ChainedValidator; + + public static function subdivisionCode(string $countryCode): ChainedValidator; + + /** + * @param mixed[] $superset + */ + public static function subset(array $superset): ChainedValidator; + + public static function symbolicLink(): ChainedValidator; + + public static function time(string $format = 'H:i:s'): ChainedValidator; + + public static function tld(): ChainedValidator; + + public static function trueVal(): ChainedValidator; + + public static function type(string $type): ChainedValidator; + + public static function unique(): ChainedValidator; + + public static function uploaded(): ChainedValidator; + + public static function uppercase(): ChainedValidator; + + public static function url(): ChainedValidator; + + public static function uuid(?int $version = null): ChainedValidator; + + public static function version(): ChainedValidator; + + public static function videoUrl(?string $service = null): ChainedValidator; + + public static function vowel(string ...$additionalChars): ChainedValidator; + + public static function when(Validatable $if, Validatable $then, ?Validatable $else = null): ChainedValidator; + + public static function writable(): ChainedValidator; + + public static function xdigit(string ...$additionalChars): ChainedValidator; + + public static function yes(bool $useLocale = false): ChainedValidator; +} diff --git a/cacme/vendor/workerman/validation/library/Validatable.php b/cacme/vendor/workerman/validation/library/Validatable.php new file mode 100644 index 0000000..6f07aab --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Validatable.php @@ -0,0 +1,48 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation; + +use Respect\Validation\Exceptions\ValidationException; + +/** Interface for validation rules */ +/** + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +interface Validatable +{ + /** + * @param mixed $input + */ + public function assert($input): void; + + /** + * @param mixed $input + */ + public function check($input): void; + + public function getName(): ?string; + + /** + * @param mixed $input + * @param mixed[] $extraParameters + */ + public function reportError($input, array $extraParameters = []): ValidationException; + + public function setName(string $name): Validatable; + + public function setTemplate(string $template): Validatable; + + public function setDefault(string $default, bool $defaultType=false): Validatable; + /** + * @param mixed $input + */ + public function validate($input): bool; +} diff --git a/cacme/vendor/workerman/validation/library/Validator.php b/cacme/vendor/workerman/validation/library/Validator.php new file mode 100644 index 0000000..1ffceb3 --- /dev/null +++ b/cacme/vendor/workerman/validation/library/Validator.php @@ -0,0 +1,99 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation; + +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Exceptions\ValidationException; +use Respect\Validation\Rules\AllOf; + +use function count; + +/** + * @mixin StaticValidator + * + * @author Alexandre Gomes Gaigalas + * @author Henrique Moody + */ +final class Validator extends AllOf +{ + /** + * Create instance validator. + */ + public static function create(): self + { + return new self(); + } + + /** + * {@inheritDoc} + */ + public function check($input): void + { + try { + parent::check($input); + } catch (ValidationException $exception) { + if (count($this->getRules()) == 1 && $this->template) { + $exception->updateTemplate($this->template); + } + + throw $exception; + } + } + + /** + * Creates a new Validator instance with a rule that was called on the static method. + * + * @param mixed[] $arguments + * + * @throws ComponentException + */ + public static function __callStatic(string $ruleName, array $arguments): self + { + return self::create()->__call($ruleName, $arguments); + } + + /** + * Create a new rule by the name of the method and adds the rule to the chain. + * + * @param mixed[] $arguments + * + * @throws ComponentException + */ + public function __call(string $ruleName, array $arguments): self + { + $this->addRule(Factory::getDefaultInstance()->rule($ruleName, $arguments)); + + return $this; + } + + + /** + * 按照规则检查输入,如果不符合规则则抛出异常 + * + * @param array $input + * @param array $rules + * @return array + */ + public static function input(array $input, array $rules) + { + $values = []; + foreach ($rules as $field => $rule) { + if(is_array($rule) || !($rule instanceof \Respect\Validation\Validator)){ + $values[$field] = $rule; + }else{ + $value = $rule->defaultType?$rule->default:($input[$field] ?? $rule->default); + $rule->check($value); + $values[$field] = $value; + } + } + return $values; + } + +} diff --git a/cacme/vendor/workerman/webman-framework/.gitignore b/cacme/vendor/workerman/webman-framework/.gitignore new file mode 100644 index 0000000..3f2c43a --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/.gitignore @@ -0,0 +1,5 @@ +composer.lock +vendor +vendor/ +.idea +.idea/ \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/README.md b/cacme/vendor/workerman/webman-framework/README.md new file mode 100644 index 0000000..96a900a --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/README.md @@ -0,0 +1,5 @@ +# webman-framework +Note: This repository is the core code of the webman framework. If you want to build an application using webman, visit the main [webman](https://github.com/walkor/webman) repository. + +## LICENSE +MIT diff --git a/cacme/vendor/workerman/webman-framework/composer.json b/cacme/vendor/workerman/webman-framework/composer.json new file mode 100644 index 0000000..53c9308 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/composer.json @@ -0,0 +1,47 @@ +{ + "name": "workerman/webman-framework", + "type": "library", + "keywords": [ + "high performance", + "http service" + ], + "homepage": "https://www.workerman.net", + "license": "MIT", + "description": "High performance HTTP Service Framework.", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/walkor/webman/issues", + "forum": "https://wenda.workerman.net/", + "wiki": "https://doc.workerman.net/", + "source": "https://github.com/walkor/webman-framework" + }, + "require": { + "php": ">=7.2", + "ext-json": "*", + "workerman/workerman": "^4.0.4 || ^5.0.0", + "nikic/fast-route": "^1.3", + "psr/container": ">=1.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "autoload": { + "psr-4": { + "Webman\\": "./src", + "support\\": "./src/support", + "Support\\": "./src/support", + "Support\\Bootstrap\\": "./src/support/bootstrap", + "Support\\Exception\\": "./src/support/exception", + "Support\\View\\": "./src/support/view" + } + }, + "minimum-stability": "dev" +} diff --git a/cacme/vendor/workerman/webman-framework/src/App.php b/cacme/vendor/workerman/webman-framework/src/App.php new file mode 100644 index 0000000..ce51b8c --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/App.php @@ -0,0 +1,939 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use Closure; +use Exception; +use FastRoute\Dispatcher; +use InvalidArgumentException; +use Monolog\Logger; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; +use ReflectionClass; +use ReflectionException; +use ReflectionFunction; +use ReflectionFunctionAbstract; +use ReflectionMethod; +use Throwable; +use Webman\Exception\ExceptionHandler; +use Webman\Exception\ExceptionHandlerInterface; +use Webman\Http\Request; +use Webman\Http\Response; +use Webman\Route\Route as RouteObject; +use Workerman\Connection\TcpConnection; +use Workerman\Protocols\Http; +use Workerman\Worker; +use function array_merge; +use function array_pop; +use function array_reduce; +use function array_reverse; +use function array_splice; +use function array_values; +use function class_exists; +use function clearstatcache; +use function count; +use function current; +use function end; +use function explode; +use function file_get_contents; +use function get_class_methods; +use function gettype; +use function implode; +use function in_array; +use function is_a; +use function is_array; +use function is_dir; +use function is_file; +use function is_string; +use function key; +use function method_exists; +use function next; +use function ob_get_clean; +use function ob_start; +use function pathinfo; +use function scandir; +use function str_replace; +use function strpos; +use function strtolower; +use function substr; +use function trim; + +/** + * Class App + * @package Webman + */ +class App +{ + + /** + * @var callable[] + */ + protected static $callbacks = []; + + /** + * @var Worker + */ + protected static $worker = null; + + /** + * @var Logger + */ + protected static $logger = null; + + /** + * @var string + */ + protected static $appPath = ''; + + /** + * @var string + */ + protected static $publicPath = ''; + + /** + * @var string + */ + protected static $requestClass = ''; + + /** + * App constructor. + * @param string $requestClass + * @param Logger $logger + * @param string $appPath + * @param string $publicPath + */ + public function __construct(string $requestClass, Logger $logger, string $appPath, string $publicPath) + { + static::$requestClass = $requestClass; + static::$logger = $logger; + static::$publicPath = $publicPath; + static::$appPath = $appPath; + } + + /** + * OnMessage. + * @param TcpConnection|mixed $connection + * @param Request|mixed $request + * @return null + */ + public function onMessage($connection, $request) + { + try { + Context::set(Request::class, $request); + $path = $request->path(); + $key = $request->method() . $path; + if (isset(static::$callbacks[$key])) { + [$callback, $request->plugin, $request->app, $request->controller, $request->action, $request->route] = static::$callbacks[$key]; + static::send($connection, $callback($request), $request); + return null; + } + + if ( + static::unsafeUri($connection, $path, $request) || + static::findFile($connection, $path, $key, $request) || + static::findRoute($connection, $path, $key, $request) + ) { + return null; + } + + $controllerAndAction = static::parseControllerAction($path); + $plugin = $controllerAndAction['plugin'] ?? static::getPluginByPath($path); + if (!$controllerAndAction || Route::hasDisableDefaultRoute($plugin)) { + $request->plugin = $plugin; + $callback = static::getFallback($plugin); + $request->app = $request->controller = $request->action = ''; + static::send($connection, $callback($request), $request); + return null; + } + $app = $controllerAndAction['app']; + $controller = $controllerAndAction['controller']; + $action = $controllerAndAction['action']; + $callback = static::getCallback($plugin, $app, [$controller, $action]); + static::collectCallbacks($key, [$callback, $plugin, $app, $controller, $action, null]); + [$callback, $request->plugin, $request->app, $request->controller, $request->action, $request->route] = static::$callbacks[$key]; + static::send($connection, $callback($request), $request); + } catch (Throwable $e) { + static::send($connection, static::exceptionResponse($e, $request), $request); + } + return null; + } + + /** + * OnWorkerStart. + * @param $worker + * @return void + */ + public function onWorkerStart($worker) + { + static::$worker = $worker; + Http::requestClass(static::$requestClass); + } + + /** + * CollectCallbacks. + * @param string $key + * @param array $data + * @return void + */ + protected static function collectCallbacks(string $key, array $data) + { + static::$callbacks[$key] = $data; + if (count(static::$callbacks) >= 1024) { + unset(static::$callbacks[key(static::$callbacks)]); + } + } + + /** + * UnsafeUri. + * @param TcpConnection $connection + * @param string $path + * @param $request + * @return bool + */ + protected static function unsafeUri(TcpConnection $connection, string $path, $request): bool + { + if ( + !$path || + strpos($path, '..') !== false || + strpos($path, "\\") !== false || + strpos($path, "\0") !== false + ) { + $callback = static::getFallback(); + $request->plugin = $request->app = $request->controller = $request->action = ''; + static::send($connection, $callback($request), $request); + return true; + } + return false; + } + + /** + * GetFallback. + * @param string $plugin + * @return Closure + */ + protected static function getFallback(string $plugin = ''): Closure + { + // when route, controller and action not found, try to use Route::fallback + return Route::getFallback($plugin) ?: function () { + try { + $notFoundContent = file_get_contents(static::$publicPath . '/404.html'); + } catch (Throwable $e) { + $notFoundContent = '404 Not Found'; + } + return new Response(404, [], $notFoundContent); + }; + } + + /** + * ExceptionResponse. + * @param Throwable $e + * @param $request + * @return Response + */ + protected static function exceptionResponse(Throwable $e, $request): Response + { + try { + $app = $request->app ?: ''; + $plugin = $request->plugin ?: ''; + $exceptionConfig = static::config($plugin, 'exception'); + $defaultException = $exceptionConfig[''] ?? ExceptionHandler::class; + $exceptionHandlerClass = $exceptionConfig[$app] ?? $defaultException; + + /** @var ExceptionHandlerInterface $exceptionHandler */ + $exceptionHandler = static::container($plugin)->make($exceptionHandlerClass, [ + 'logger' => static::$logger, + 'debug' => static::config($plugin, 'app.debug') + ]); + $exceptionHandler->report($e); + $response = $exceptionHandler->render($request, $e); + $response->exception($e); + return $response; + } catch (Throwable $e) { + $response = new Response(500, [], static::config($plugin ?? '', 'app.debug') ? (string)$e : $e->getMessage()); + $response->exception($e); + return $response; + } + } + + /** + * GetCallback. + * @param string $plugin + * @param string $app + * @param $call + * @param array|null $args + * @param bool $withGlobalMiddleware + * @param RouteObject|null $route + * @return callable + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws ReflectionException + */ + protected static function getCallback(string $plugin, string $app, $call, array $args = null, bool $withGlobalMiddleware = true, RouteObject $route = null) + { + $args = $args === null ? null : array_values($args); + $middlewares = []; + if ($route) { + $routeMiddlewares = $route->getMiddleware(); + foreach ($routeMiddlewares as $className) { + $middlewares[] = [$className, 'process']; + } + } + $middlewares = array_merge($middlewares, Middleware::getMiddleware($plugin, $app, $withGlobalMiddleware)); + + foreach ($middlewares as $key => $item) { + $middleware = $item[0]; + if (is_string($middleware)) { + $middleware = static::container($plugin)->get($middleware); + } elseif ($middleware instanceof Closure) { + $middleware = call_user_func($middleware, static::container($plugin)); + } + if (!$middleware instanceof MiddlewareInterface) { + throw new InvalidArgumentException('Not support middleware type'); + } + $middlewares[$key][0] = $middleware; + } + + $needInject = static::isNeedInject($call, $args); + if (is_array($call) && is_string($call[0])) { + $controllerReuse = static::config($plugin, 'app.controller_reuse', true); + if (!$controllerReuse) { + if ($needInject) { + $call = function ($request, ...$args) use ($call, $plugin) { + $call[0] = static::container($plugin)->make($call[0]); + $reflector = static::getReflector($call); + $args = static::resolveMethodDependencies($plugin, $request, $args, $reflector); + return $call(...$args); + }; + $needInject = false; + } else { + $call = function ($request, ...$args) use ($call, $plugin) { + $call[0] = static::container($plugin)->make($call[0]); + return $call($request, ...$args); + }; + } + } else { + $call[0] = static::container($plugin)->get($call[0]); + } + } + + if ($needInject) { + $call = static::resolveInject($plugin, $call); + } + + if ($middlewares) { + $callback = array_reduce($middlewares, function ($carry, $pipe) { + return function ($request) use ($carry, $pipe) { + try { + return $pipe($request, $carry); + } catch (Throwable $e) { + return static::exceptionResponse($e, $request); + } + }; + }, function ($request) use ($call, $args) { + try { + if ($args === null) { + $response = $call($request); + } else { + $response = $call($request, ...$args); + } + } catch (Throwable $e) { + return static::exceptionResponse($e, $request); + } + if (!$response instanceof Response) { + if (!is_string($response)) { + $response = static::stringify($response); + } + $response = new Response(200, [], $response); + } + return $response; + }); + } else { + if ($args === null) { + $callback = $call; + } else { + $callback = function ($request) use ($call, $args) { + return $call($request, ...$args); + }; + } + } + return $callback; + } + + /** + * ResolveInject. + * @param string $plugin + * @param array|Closure $call + * @return Closure + * @see Dependency injection through reflection information + */ + protected static function resolveInject(string $plugin, $call): Closure + { + return function (Request $request, ...$args) use ($plugin, $call) { + $reflector = static::getReflector($call); + $args = static::resolveMethodDependencies($plugin, $request, $args, $reflector); + return $call(...$args); + }; + } + + /** + * Check whether inject is required. + * @param $call + * @param $args + * @return bool + * @throws ReflectionException + */ + protected static function isNeedInject($call, $args): bool + { + if (is_array($call) && !method_exists($call[0], $call[1])) { + return false; + } + $args = $args ?: []; + $reflector = static::getReflector($call); + $reflectionParameters = $reflector->getParameters(); + if (!$reflectionParameters) { + return false; + } + $firstParameter = current($reflectionParameters); + unset($reflectionParameters[key($reflectionParameters)]); + $adaptersList = ['int', 'string', 'bool', 'array', 'object', 'float', 'mixed', 'resource']; + foreach ($reflectionParameters as $parameter) { + if ($parameter->hasType() && !in_array($parameter->getType()->getName(), $adaptersList)) { + return true; + } + } + if (!$firstParameter->hasType()) { + return count($args) > count($reflectionParameters); + } + + if (!is_a(static::$requestClass, $firstParameter->getType()->getName())) { + return true; + } + + return false; + } + + /** + * Get reflector. + * @param $call + * @return ReflectionFunction|ReflectionMethod + * @throws ReflectionException + */ + protected static function getReflector($call) + { + if ($call instanceof Closure || is_string($call)) { + return new ReflectionFunction($call); + } + return new ReflectionMethod($call[0], $call[1]); + } + + /** + * Return dependent parameters + * @param string $plugin + * @param Request $request + * @param array $args + * @param ReflectionFunctionAbstract $reflector + * @return array + */ + protected static function resolveMethodDependencies(string $plugin, Request $request, array $args, ReflectionFunctionAbstract $reflector): array + { + // Specification parameter information + $args = array_values($args); + $parameters = []; + // An array of reflection classes for loop parameters, with each $parameter representing a reflection object of parameters + foreach ($reflector->getParameters() as $parameter) { + // Parameter quota consumption + if ($parameter->hasType()) { + $name = $parameter->getType()->getName(); + switch ($name) { + case 'int': + case 'string': + case 'bool': + case 'array': + case 'object': + case 'float': + case 'mixed': + case 'resource': + goto _else; + default: + if (is_a($request, $name)) { + //Inject Request + $parameters[] = $request; + } else { + $parameters[] = static::container($plugin)->make($name); + } + break; + } + } else { + _else: + // The variable parameter + if (null !== key($args)) { + $parameters[] = current($args); + } else { + // Indicates whether the current parameter has a default value. If yes, return true + $parameters[] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null; + } + // Quota of consumption variables + next($args); + } + } + + // Returns the result of parameters replacement + return $parameters; + } + + /** + * Container. + * @param string $plugin + * @return ContainerInterface + */ + public static function container(string $plugin = '') + { + return static::config($plugin, 'container'); + } + + /** + * Get request. + * @return Request|\support\Request + */ + public static function request() + { + return Context::get(Request::class); + } + + /** + * Get worker. + * @return Worker + */ + public static function worker(): ?Worker + { + return static::$worker; + } + + /** + * Find Route. + * @param TcpConnection $connection + * @param string $path + * @param string $key + * @param Request|mixed $request + * @return bool + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws ReflectionException + */ + protected static function findRoute(TcpConnection $connection, string $path, string $key, $request): bool + { + $routeInfo = Route::dispatch($request->method(), $path); + if ($routeInfo[0] === Dispatcher::FOUND) { + $routeInfo[0] = 'route'; + $callback = $routeInfo[1]['callback']; + $route = clone $routeInfo[1]['route']; + $app = $controller = $action = ''; + $args = !empty($routeInfo[2]) ? $routeInfo[2] : null; + if ($args) { + $route->setParams($args); + } + if (is_array($callback)) { + $controller = $callback[0]; + $plugin = static::getPluginByClass($controller); + $app = static::getAppByController($controller); + $action = static::getRealMethod($controller, $callback[1]) ?? ''; + } else { + $plugin = static::getPluginByPath($path); + } + $callback = static::getCallback($plugin, $app, $callback, $args, true, $route); + static::collectCallbacks($key, [$callback, $plugin, $app, $controller ?: '', $action, $route]); + [$callback, $request->plugin, $request->app, $request->controller, $request->action, $request->route] = static::$callbacks[$key]; + static::send($connection, $callback($request), $request); + return true; + } + return false; + } + + /** + * Find File. + * @param TcpConnection $connection + * @param string $path + * @param string $key + * @param Request|mixed $request + * @return bool + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws ReflectionException + */ + protected static function findFile(TcpConnection $connection, string $path, string $key, $request): bool + { + if (preg_match('/%[0-9a-f]{2}/i', $path)) { + $path = urldecode($path); + if (static::unsafeUri($connection, $path, $request)) { + return true; + } + } + + $pathExplodes = explode('/', trim($path, '/')); + $plugin = ''; + if (isset($pathExplodes[1]) && $pathExplodes[0] === 'app') { + $publicDir = BASE_PATH . "/plugin/$pathExplodes[1]/public"; + $plugin = $pathExplodes[1]; + $path = substr($path, strlen("/app/$pathExplodes[1]/")); + } else { + $publicDir = static::$publicPath; + } + $file = "$publicDir/$path"; + if (!is_file($file)) { + return false; + } + + if (pathinfo($file, PATHINFO_EXTENSION) === 'php') { + if (!static::config($plugin, 'app.support_php_files', false)) { + return false; + } + static::collectCallbacks($key, [function () use ($file) { + return static::execPhpFile($file); + }, '', '', '', '', null]); + [, $request->plugin, $request->app, $request->controller, $request->action, $request->route] = static::$callbacks[$key]; + static::send($connection, static::execPhpFile($file), $request); + return true; + } + + if (!static::config($plugin, 'static.enable', false)) { + return false; + } + + static::collectCallbacks($key, [static::getCallback($plugin, '__static__', function ($request) use ($file, $plugin) { + clearstatcache(true, $file); + if (!is_file($file)) { + $callback = static::getFallback($plugin); + return $callback($request); + } + return (new Response())->file($file); + }, null, false), '', '', '', '', null]); + [$callback, $request->plugin, $request->app, $request->controller, $request->action, $request->route] = static::$callbacks[$key]; + static::send($connection, $callback($request), $request); + return true; + } + + /** + * Send. + * @param TcpConnection|mixed $connection + * @param mixed $response + * @param Request|mixed $request + * @return void + */ + protected static function send($connection, $response, $request) + { + $keepAlive = $request->header('connection'); + Context::destroy(); + if (($keepAlive === null && $request->protocolVersion() === '1.1') + || $keepAlive === 'keep-alive' || $keepAlive === 'Keep-Alive' + ) { + $connection->send($response); + return; + } + $connection->close($response); + } + + /** + * ParseControllerAction. + * @param string $path + * @return array|false + * @throws ReflectionException + */ + protected static function parseControllerAction(string $path) + { + $path = str_replace('-', '', $path); + static $cache = []; + if (isset($cache[$path])) { + return $cache[$path]; + } + $pathExplode = explode('/', trim($path, '/')); + $isPlugin = isset($pathExplode[1]) && $pathExplode[0] === 'app'; + $configPrefix = $isPlugin ? "plugin.$pathExplode[1]." : ''; + $pathPrefix = $isPlugin ? "/app/$pathExplode[1]" : ''; + $classPrefix = $isPlugin ? "plugin\\$pathExplode[1]" : ''; + $suffix = Config::get("{$configPrefix}app.controller_suffix", ''); + $relativePath = trim(substr($path, strlen($pathPrefix)), '/'); + $pathExplode = $relativePath ? explode('/', $relativePath) : []; + + $action = 'index'; + if (!$controllerAction = static::guessControllerAction($pathExplode, $action, $suffix, $classPrefix)) { + if (count($pathExplode) <= 1) { + return false; + } + $action = end($pathExplode); + unset($pathExplode[count($pathExplode) - 1]); + $controllerAction = static::guessControllerAction($pathExplode, $action, $suffix, $classPrefix); + } + if ($controllerAction && !isset($path[256])) { + $cache[$path] = $controllerAction; + if (count($cache) > 1024) { + unset($cache[key($cache)]); + } + } + return $controllerAction; + } + + /** + * GuessControllerAction. + * @param $pathExplode + * @param $action + * @param $suffix + * @param $classPrefix + * @return array|false + * @throws ReflectionException + */ + protected static function guessControllerAction($pathExplode, $action, $suffix, $classPrefix) + { + $map[] = trim("$classPrefix\\app\\controller\\" . implode('\\', $pathExplode), '\\'); + foreach ($pathExplode as $index => $section) { + $tmp = $pathExplode; + array_splice($tmp, $index, 1, [$section, 'controller']); + $map[] = trim("$classPrefix\\" . implode('\\', array_merge(['app'], $tmp)), '\\'); + } + foreach ($map as $item) { + $map[] = $item . '\\index'; + } + + foreach ($map as $controllerClass) { + // Remove xx\xx\controller + if (substr($controllerClass, -11) === '\\controller') { + continue; + } + $controllerClass .= $suffix; + if ($controllerAction = static::getControllerAction($controllerClass, $action)) { + return $controllerAction; + } + } + return false; + } + + /** + * GetControllerAction. + * @param string $controllerClass + * @param string $action + * @return array|false + * @throws ReflectionException + */ + protected static function getControllerAction(string $controllerClass, string $action) + { + // Disable calling magic methods + if (strpos($action, '__') === 0) { + return false; + } + if (($controllerClass = static::getController($controllerClass)) && ($action = static::getAction($controllerClass, $action))) { + return [ + 'plugin' => static::getPluginByClass($controllerClass), + 'app' => static::getAppByController($controllerClass), + 'controller' => $controllerClass, + 'action' => $action + ]; + } + return false; + } + + /** + * GetController. + * @param string $controllerClass + * @return string|false + * @throws ReflectionException + */ + protected static function getController(string $controllerClass) + { + if (class_exists($controllerClass)) { + return (new ReflectionClass($controllerClass))->name; + } + $explodes = explode('\\', strtolower(ltrim($controllerClass, '\\'))); + $basePath = $explodes[0] === 'plugin' ? BASE_PATH . '/plugin' : static::$appPath; + unset($explodes[0]); + $fileName = array_pop($explodes) . '.php'; + $found = true; + foreach ($explodes as $pathSection) { + if (!$found) { + break; + } + $dirs = Util::scanDir($basePath, false); + $found = false; + foreach ($dirs as $name) { + $path = "$basePath/$name"; + if (is_dir($path) && strtolower($name) === $pathSection) { + $basePath = $path; + $found = true; + break; + } + } + } + if (!$found) { + return false; + } + foreach (scandir($basePath) ?: [] as $name) { + if (strtolower($name) === $fileName) { + require_once "$basePath/$name"; + if (class_exists($controllerClass, false)) { + return (new ReflectionClass($controllerClass))->name; + } + } + } + return false; + } + + /** + * GetAction. + * @param string $controllerClass + * @param string $action + * @return string|false + */ + protected static function getAction(string $controllerClass, string $action) + { + $methods = get_class_methods($controllerClass); + $action = strtolower($action); + $found = false; + foreach ($methods as $candidate) { + if (strtolower($candidate) === $action) { + $action = $candidate; + $found = true; + break; + } + } + if ($found) { + return $action; + } + // Action is not public method + if (method_exists($controllerClass, $action)) { + return false; + } + if (method_exists($controllerClass, '__call')) { + return $action; + } + return false; + } + + /** + * GetPluginByClass. + * @param string $controllerClass + * @return mixed|string + */ + public static function getPluginByClass(string $controllerClass) + { + $controllerClass = trim($controllerClass, '\\'); + $tmp = explode('\\', $controllerClass, 3); + if ($tmp[0] !== 'plugin') { + return ''; + } + return $tmp[1] ?? ''; + } + + /** + * GetPluginByPath. + * @param string $path + * @return mixed|string + */ + public static function getPluginByPath(string $path) + { + $path = trim($path, '/'); + $tmp = explode('/', $path, 3); + if ($tmp[0] !== 'app') { + return ''; + } + return $tmp[1] ?? ''; + } + + /** + * GetAppByController. + * @param string $controllerClass + * @return mixed|string + */ + protected static function getAppByController(string $controllerClass) + { + $controllerClass = trim($controllerClass, '\\'); + $tmp = explode('\\', $controllerClass, 5); + $pos = $tmp[0] === 'plugin' ? 3 : 1; + if (!isset($tmp[$pos])) { + return ''; + } + return strtolower($tmp[$pos]) === 'controller' ? '' : $tmp[$pos]; + } + + /** + * ExecPhpFile. + * @param string $file + * @return false|string + */ + public static function execPhpFile(string $file) + { + ob_start(); + // Try to include php file. + try { + include $file; + } catch (Exception $e) { + echo $e; + } + return ob_get_clean(); + } + + /** + * GetRealMethod. + * @param string $class + * @param string $method + * @return string + */ + protected static function getRealMethod(string $class, string $method): string + { + $method = strtolower($method); + $methods = get_class_methods($class); + foreach ($methods as $candidate) { + if (strtolower($candidate) === $method) { + return $candidate; + } + } + return $method; + } + + /** + * Config. + * @param string $plugin + * @param string $key + * @param $default + * @return array|mixed|null + */ + protected static function config(string $plugin, string $key, $default = null) + { + return Config::get($plugin ? "plugin.$plugin.$key" : $key, $default); + } + + + /** + * @param mixed $data + * @return string + */ + protected static function stringify($data): string + { + $type = gettype($data); + switch ($type) { + case 'boolean': + return $data ? 'true' : 'false'; + case 'NULL': + return 'NULL'; + case 'array': + return 'Array'; + case 'object': + if (!method_exists($data, '__toString')) { + return 'Object'; + } + default: + return (string)$data; + } + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/Bootstrap.php b/cacme/vendor/workerman/webman-framework/src/Bootstrap.php new file mode 100644 index 0000000..50774a1 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Bootstrap.php @@ -0,0 +1,28 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use Workerman\Worker; + +interface Bootstrap +{ + /** + * onWorkerStart + * + * @param Worker|null $worker + * @return mixed + */ + public static function start(?Worker $worker); +} diff --git a/cacme/vendor/workerman/webman-framework/src/Config.php b/cacme/vendor/workerman/webman-framework/src/Config.php new file mode 100644 index 0000000..b0f4918 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Config.php @@ -0,0 +1,296 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use function array_replace_recursive; +use function array_reverse; +use function count; +use function explode; +use function in_array; +use function is_array; +use function is_dir; +use function is_file; +use function key; +use function str_replace; + +class Config +{ + + /** + * @var array + */ + protected static $config = []; + + /** + * @var string + */ + protected static $configPath = ''; + + /** + * @var bool + */ + protected static $loaded = false; + + /** + * Load. + * @param string $configPath + * @param array $excludeFile + * @param string|null $key + * @return void + */ + public static function load(string $configPath, array $excludeFile = [], string $key = null) + { + static::$configPath = $configPath; + if (!$configPath) { + return; + } + static::$loaded = false; + $config = static::loadFromDir($configPath, $excludeFile); + if (!$config) { + static::$loaded = true; + return; + } + if ($key !== null) { + foreach (array_reverse(explode('.', $key)) as $k) { + $config = [$k => $config]; + } + } + static::$config = array_replace_recursive(static::$config, $config); + static::formatConfig(); + static::$loaded = true; + } + + /** + * This deprecated method will certainly be removed in the future. + * @param string $configPath + * @param array $excludeFile + * @return void + * @deprecated + */ + public static function reload(string $configPath, array $excludeFile = []) + { + static::load($configPath, $excludeFile); + } + + /** + * Clear. + * @return void + */ + public static function clear() + { + static::$config = []; + } + + /** + * FormatConfig. + * @return void + */ + protected static function formatConfig() + { + $config = static::$config; + // Merge log config + foreach ($config['plugin'] ?? [] as $firm => $projects) { + if (isset($projects['app'])) { + foreach ($projects['log'] ?? [] as $key => $item) { + $config['log']["plugin.$firm.$key"] = $item; + } + } + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['log'] ?? [] as $key => $item) { + $config['log']["plugin.$firm.$name.$key"] = $item; + } + } + } + // Merge database config + foreach ($config['plugin'] ?? [] as $firm => $projects) { + if (isset($projects['app'])) { + foreach ($projects['database']['connections'] ?? [] as $key => $connection) { + $config['database']['connections']["plugin.$firm.$key"] = $connection; + } + } + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['database']['connections'] ?? [] as $key => $connection) { + $config['database']['connections']["plugin.$firm.$name.$key"] = $connection; + } + } + } + if (!empty($config['database']['connections'])) { + $config['database']['default'] = $config['database']['default'] ?? key($config['database']['connections']); + } + // Merge thinkorm config + foreach ($config['plugin'] ?? [] as $firm => $projects) { + if (isset($projects['app'])) { + foreach ($projects['thinkorm']['connections'] ?? [] as $key => $connection) { + $config['thinkorm']['connections']["plugin.$firm.$key"] = $connection; + } + } + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['thinkorm']['connections'] ?? [] as $key => $connection) { + $config['thinkorm']['connections']["plugin.$firm.$name.$key"] = $connection; + } + } + } + if (!empty($config['thinkorm']['connections'])) { + $config['thinkorm']['default'] = $config['thinkorm']['default'] ?? key($config['thinkorm']['connections']); + } + // Merge redis config + foreach ($config['plugin'] ?? [] as $firm => $projects) { + if (isset($projects['app'])) { + foreach ($projects['redis'] ?? [] as $key => $connection) { + $config['redis']["plugin.$firm.$key"] = $connection; + } + } + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['redis'] ?? [] as $key => $connection) { + $config['redis']["plugin.$firm.$name.$key"] = $connection; + } + } + } + static::$config = $config; + } + + /** + * LoadFromDir. + * @param string $configPath + * @param array $excludeFile + * @return array + */ + public static function loadFromDir(string $configPath, array $excludeFile = []): array + { + $allConfig = []; + $dirIterator = new RecursiveDirectoryIterator($configPath, FilesystemIterator::FOLLOW_SYMLINKS); + $iterator = new RecursiveIteratorIterator($dirIterator); + foreach ($iterator as $file) { + /** var SplFileInfo $file */ + if (is_dir($file) || $file->getExtension() != 'php' || in_array($file->getBaseName('.php'), $excludeFile)) { + continue; + } + $appConfigFile = $file->getPath() . '/app.php'; + if (!is_file($appConfigFile)) { + continue; + } + $relativePath = str_replace($configPath . DIRECTORY_SEPARATOR, '', substr($file, 0, -4)); + $explode = array_reverse(explode(DIRECTORY_SEPARATOR, $relativePath)); + if (count($explode) >= 2) { + $appConfig = include $appConfigFile; + if (empty($appConfig['enable'])) { + continue; + } + } + $config = include $file; + foreach ($explode as $section) { + $tmp = []; + $tmp[$section] = $config; + $config = $tmp; + } + $allConfig = array_replace_recursive($allConfig, $config); + } + return $allConfig; + } + + /** + * Get. + * @param string|null $key + * @param mixed $default + * @return array|mixed|void|null + */ + public static function get(string $key = null, $default = null) + { + if ($key === null) { + return static::$config; + } + $keyArray = explode('.', $key); + $value = static::$config; + $found = true; + foreach ($keyArray as $index) { + if (!isset($value[$index])) { + if (static::$loaded) { + return $default; + } + $found = false; + break; + } + $value = $value[$index]; + } + if ($found) { + return $value; + } + return static::read($key, $default); + } + + /** + * Read. + * @param string $key + * @param mixed $default + * @return array|mixed|null + */ + protected static function read(string $key, $default = null) + { + $path = static::$configPath; + if ($path === '') { + return $default; + } + $keys = $keyArray = explode('.', $key); + foreach ($keyArray as $index => $section) { + unset($keys[$index]); + if (is_file($file = "$path/$section.php")) { + $config = include $file; + return static::find($keys, $config, $default); + } + if (!is_dir($path = "$path/$section")) { + return $default; + } + } + return $default; + } + + /** + * Find. + * @param array $keyArray + * @param mixed $stack + * @param mixed $default + * @return array|mixed + */ + protected static function find(array $keyArray, $stack, $default) + { + if (!is_array($stack)) { + return $default; + } + $value = $stack; + foreach ($keyArray as $index) { + if (!isset($value[$index])) { + return $default; + } + $value = $value[$index]; + } + return $value; + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Container.php b/cacme/vendor/workerman/webman-framework/src/Container.php new file mode 100644 index 0000000..ef39377 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Container.php @@ -0,0 +1,84 @@ +instances[$name])) { + if (isset($this->definitions[$name])) { + $this->instances[$name] = call_user_func($this->definitions[$name], $this); + } else { + if (!class_exists($name)) { + throw new NotFoundException("Class '$name' not found"); + } + $this->instances[$name] = new $name(); + } + } + return $this->instances[$name]; + } + + /** + * Has. + * @param string $name + * @return bool + */ + public function has(string $name): bool + { + return array_key_exists($name, $this->instances) + || array_key_exists($name, $this->definitions); + } + + /** + * Make. + * @param string $name + * @param array $constructor + * @return mixed + * @throws NotFoundException + */ + public function make(string $name, array $constructor = []) + { + if (!class_exists($name)) { + throw new NotFoundException("Class '$name' not found"); + } + return new $name(... array_values($constructor)); + } + + /** + * AddDefinitions. + * @param array $definitions + * @return $this + */ + public function addDefinitions(array $definitions): Container + { + $this->definitions = array_merge($this->definitions, $definitions); + return $this; + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Context.php b/cacme/vendor/workerman/webman-framework/src/Context.php new file mode 100644 index 0000000..b72abf7 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Context.php @@ -0,0 +1,129 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use Fiber; +use SplObjectStorage; +use StdClass; +use Swow\Coroutine; +use WeakMap; +use Workerman\Events\Revolt; +use Workerman\Events\Swoole; +use Workerman\Events\Swow; +use Workerman\Worker; +use function property_exists; + +/** + * Class Context + * @package Webman + */ +class Context +{ + + /** + * @var SplObjectStorage|WeakMap + */ + protected static $objectStorage; + + /** + * @var StdClass + */ + protected static $object; + + /** + * @return StdClass + */ + protected static function getObject(): StdClass + { + if (!static::$objectStorage) { + static::$objectStorage = class_exists(WeakMap::class) ? new WeakMap() : new SplObjectStorage(); + static::$object = new StdClass; + } + $key = static::getKey(); + if (!isset(static::$objectStorage[$key])) { + static::$objectStorage[$key] = new StdClass; + } + return static::$objectStorage[$key]; + } + + /** + * @return mixed + */ + protected static function getKey() + { + switch (Worker::$eventLoopClass) { + case Revolt::class: + return Fiber::getCurrent(); + case Swoole::class: + return \Swoole\Coroutine::getContext(); + case Swow::class: + return Coroutine::getCurrent(); + } + return static::$object; + } + + /** + * @param string|null $key + * @return mixed + */ + public static function get(string $key = null) + { + $obj = static::getObject(); + if ($key === null) { + return $obj; + } + return $obj->$key ?? null; + } + + /** + * @param string $key + * @param $value + * @return void + */ + public static function set(string $key, $value): void + { + $obj = static::getObject(); + $obj->$key = $value; + } + + /** + * @param string $key + * @return void + */ + public static function delete(string $key): void + { + $obj = static::getObject(); + unset($obj->$key); + } + + /** + * @param string $key + * @return bool + */ + public static function has(string $key): bool + { + $obj = static::getObject(); + return property_exists($obj, $key); + } + + /** + * @return void + */ + public static function destroy(): void + { + unset(static::$objectStorage[static::getKey()]); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandler.php b/cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandler.php new file mode 100644 index 0000000..b8f53e4 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandler.php @@ -0,0 +1,118 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Exception; + +use Psr\Log\LoggerInterface; +use Throwable; +use Webman\Http\Request; +use Webman\Http\Response; +use function json_encode; +use function nl2br; +use function trim; + +/** + * Class Handler + * @package support\exception + */ +class ExceptionHandler implements ExceptionHandlerInterface +{ + /** + * @var LoggerInterface + */ + protected $logger = null; + + /** + * @var bool + */ + protected $debug = false; + + /** + * @var array + */ + public $dontReport = []; + + /** + * ExceptionHandler constructor. + * @param $logger + * @param $debug + */ + public function __construct($logger, $debug) + { + $this->logger = $logger; + $this->debug = $debug; + } + + /** + * @param Throwable $exception + * @return void + */ + public function report(Throwable $exception) + { + if ($this->shouldntReport($exception)) { + return; + } + $logs = ''; + if ($request = \request()) { + $logs = $request->getRealIp() . ' ' . $request->method() . ' ' . trim($request->fullUrl(), '/'); + } + $this->logger->error($logs . PHP_EOL . $exception); + } + + /** + * @param Request $request + * @param Throwable $exception + * @return Response + */ + public function render(Request $request, Throwable $exception): Response + { + $code = $exception->getCode(); + if ($request->expectsJson()) { + $json = ['code' => $code ?: 500, 'msg' => $this->debug ? $exception->getMessage() : 'Server internal error']; + $this->debug && $json['traces'] = (string)$exception; + return new Response(200, ['Content-Type' => 'application/json'], + json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + } + $error = $this->debug ? nl2br((string)$exception) : 'Server internal error'; + return new Response(500, [], $error); + } + + /** + * @param Throwable $e + * @return bool + */ + protected function shouldntReport(Throwable $e): bool + { + foreach ($this->dontReport as $type) { + if ($e instanceof $type) { + return true; + } + } + return false; + } + + /** + * Compatible $this->_debug + * + * @param string $name + * @return bool|null + */ + public function __get(string $name) + { + if ($name === '_debug') { + return $this->debug; + } + return null; + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandlerInterface.php b/cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandlerInterface.php new file mode 100644 index 0000000..8868707 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Exception/ExceptionHandlerInterface.php @@ -0,0 +1,35 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Exception; + +use Throwable; +use Webman\Http\Request; +use Webman\Http\Response; + +interface ExceptionHandlerInterface +{ + /** + * @param Throwable $exception + * @return mixed + */ + public function report(Throwable $exception); + + /** + * @param Request $request + * @param Throwable $exception + * @return Response + */ + public function render(Request $request, Throwable $exception): Response; +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/Exception/FileException.php b/cacme/vendor/workerman/webman-framework/src/Exception/FileException.php new file mode 100644 index 0000000..fa5dbe6 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Exception/FileException.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Exception; + +use RuntimeException; + +/** + * Class FileException + * @package Webman\Exception + */ +class FileException extends RuntimeException +{ +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/Exception/NotFoundException.php b/cacme/vendor/workerman/webman-framework/src/Exception/NotFoundException.php new file mode 100644 index 0000000..735c1d4 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Exception/NotFoundException.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Exception; + +use Psr\Container\NotFoundExceptionInterface; + +/** + * Class NotFoundException + * @package Webman\Exception + */ +class NotFoundException extends \Exception implements NotFoundExceptionInterface +{ +} diff --git a/cacme/vendor/workerman/webman-framework/src/File.php b/cacme/vendor/workerman/webman-framework/src/File.php new file mode 100644 index 0000000..a43328c --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/File.php @@ -0,0 +1,56 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use SplFileInfo; +use Webman\Exception\FileException; +use function chmod; +use function is_dir; +use function mkdir; +use function pathinfo; +use function restore_error_handler; +use function set_error_handler; +use function sprintf; +use function strip_tags; +use function umask; + +class File extends SplFileInfo +{ + + /** + * Move. + * @param string $destination + * @return File + */ + public function move(string $destination): File + { + set_error_handler(function ($type, $msg) use (&$error) { + $error = $msg; + }); + $path = pathinfo($destination, PATHINFO_DIRNAME); + if (!is_dir($path) && !mkdir($path, 0777, true)) { + restore_error_handler(); + throw new FileException(sprintf('Unable to create the "%s" directory (%s)', $path, strip_tags($error))); + } + if (!rename($this->getPathname(), $destination)) { + restore_error_handler(); + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $destination, strip_tags($error))); + } + restore_error_handler(); + @chmod($destination, 0666 & ~umask()); + return new self($destination); + } + +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/FileSessionHandler.php b/cacme/vendor/workerman/webman-framework/src/FileSessionHandler.php new file mode 100644 index 0000000..ed0b3f2 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/FileSessionHandler.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Webman; + +/** + * This deprecated class will certainly be removed in the future. + * Please use Webman\Session\FileSessionHandler + * @deprecated + * @package Webman + */ +class FileSessionHandler extends Session\FileSessionHandler +{ + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Http/Request.php b/cacme/vendor/workerman/webman-framework/src/Http/Request.php new file mode 100644 index 0000000..0690e97 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Http/Request.php @@ -0,0 +1,318 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Http; + +use Webman\Route\Route; +use function current; +use function filter_var; +use function ip2long; +use function is_array; +use function strpos; +use const FILTER_FLAG_IPV4; +use const FILTER_FLAG_NO_PRIV_RANGE; +use const FILTER_FLAG_NO_RES_RANGE; +use const FILTER_VALIDATE_IP; + +/** + * Class Request + * @package Webman\Http + */ +class Request extends \Workerman\Protocols\Http\Request +{ + /** + * @var string + */ + public $plugin = null; + + /** + * @var string + */ + public $app = null; + + /** + * @var string + */ + public $controller = null; + + /** + * @var string + */ + public $action = null; + + /** + * @var Route + */ + public $route = null; + + /** + * @return mixed|null + */ + public function all() + { + return $this->post() + $this->get(); + } + + /** + * Input + * @param string $name + * @param mixed $default + * @return mixed|null + */ + public function input(string $name, $default = null) + { + $post = $this->post(); + if (isset($post[$name])) { + return $post[$name]; + } + $get = $this->get(); + return $get[$name] ?? $default; + } + + /** + * Only + * @param array $keys + * @return array + */ + public function only(array $keys): array + { + $all = $this->all(); + $result = []; + foreach ($keys as $key) { + if (isset($all[$key])) { + $result[$key] = $all[$key]; + } + } + return $result; + } + + /** + * Except + * @param array $keys + * @return mixed|null + */ + public function except(array $keys) + { + $all = $this->all(); + foreach ($keys as $key) { + unset($all[$key]); + } + return $all; + } + + /** + * File + * @param string|null $name + * @return null|UploadFile[]|UploadFile + */ + public function file($name = null) + { + $files = parent::file($name); + if (null === $files) { + return $name === null ? [] : null; + } + if ($name !== null) { + // Multi files + if (is_array(current($files))) { + return $this->parseFiles($files); + } + return $this->parseFile($files); + } + $uploadFiles = []; + foreach ($files as $name => $file) { + // Multi files + if (is_array(current($file))) { + $uploadFiles[$name] = $this->parseFiles($file); + } else { + $uploadFiles[$name] = $this->parseFile($file); + } + } + return $uploadFiles; + } + + /** + * ParseFile + * @param array $file + * @return UploadFile + */ + protected function parseFile(array $file): UploadFile + { + return new UploadFile($file['tmp_name'], $file['name'], $file['type'], $file['error']); + } + + /** + * ParseFiles + * @param array $files + * @return array + */ + protected function parseFiles(array $files): array + { + $uploadFiles = []; + foreach ($files as $key => $file) { + if (is_array(current($file))) { + $uploadFiles[$key] = $this->parseFiles($file); + } else { + $uploadFiles[$key] = $this->parseFile($file); + } + } + return $uploadFiles; + } + + /** + * GetRemoteIp + * @return string + */ + public function getRemoteIp(): string + { + return $this->connection->getRemoteIp(); + } + + /** + * GetRemotePort + * @return int + */ + public function getRemotePort(): int + { + return $this->connection->getRemotePort(); + } + + /** + * GetLocalIp + * @return string + */ + public function getLocalIp(): string + { + return $this->connection->getLocalIp(); + } + + /** + * GetLocalPort + * @return int + */ + public function getLocalPort(): int + { + return $this->connection->getLocalPort(); + } + + /** + * GetRealIp + * @param bool $safeMode + * @return string + */ + public function getRealIp(bool $safeMode = true): string + { + $remoteIp = $this->getRemoteIp(); + if ($safeMode && !static::isIntranetIp($remoteIp)) { + return $remoteIp; + } + $ip = $this->header('x-real-ip', $this->header('x-forwarded-for', + $this->header('client-ip', $this->header('x-client-ip', + $this->header('via', $remoteIp))))); + return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : $remoteIp; + } + + /** + * Url + * @return string + */ + public function url(): string + { + return '//' . $this->host() . $this->path(); + } + + /** + * FullUrl + * @return string + */ + public function fullUrl(): string + { + return '//' . $this->host() . $this->uri(); + } + + /** + * IsAjax + * @return bool + */ + public function isAjax(): bool + { + return $this->header('X-Requested-With') === 'XMLHttpRequest'; + } + + /** + * IsPjax + * @return bool + */ + public function isPjax(): bool + { + return (bool)$this->header('X-PJAX'); + } + + /** + * ExpectsJson + * @return bool + */ + public function expectsJson(): bool + { + return ($this->isAjax() && !$this->isPjax()) || $this->acceptJson(); + } + + /** + * AcceptJson + * @return bool + */ + public function acceptJson(): bool + { + return false !== strpos($this->header('accept', ''), 'json'); + } + + /** + * IsIntranetIp + * @param string $ip + * @return bool + */ + public static function isIntranetIp(string $ip): bool + { + // Not validate ip . + if (!filter_var($ip, FILTER_VALIDATE_IP)) { + return false; + } + // Is intranet ip ? For IPv4, the result of false may not be accurate, so we need to check it manually later . + if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) { + return true; + } + // Manual check only for IPv4 . + if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + return false; + } + // Manual check . + $reservedIps = [ + 1681915904 => 1686110207, // 100.64.0.0 - 100.127.255.255 + 3221225472 => 3221225727, // 192.0.0.0 - 192.0.0.255 + 3221225984 => 3221226239, // 192.0.2.0 - 192.0.2.255 + 3227017984 => 3227018239, // 192.88.99.0 - 192.88.99.255 + 3323068416 => 3323199487, // 198.18.0.0 - 198.19.255.255 + 3325256704 => 3325256959, // 198.51.100.0 - 198.51.100.255 + 3405803776 => 3405804031, // 203.0.113.0 - 203.0.113.255 + 3758096384 => 4026531839, // 224.0.0.0 - 239.255.255.255 + ]; + $ipLong = ip2long($ip); + foreach ($reservedIps as $ipStart => $ipEnd) { + if (($ipLong >= $ipStart) && ($ipLong <= $ipEnd)) { + return true; + } + } + return false; + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Http/Response.php b/cacme/vendor/workerman/webman-framework/src/Http/Response.php new file mode 100644 index 0000000..8d1d1a3 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Http/Response.php @@ -0,0 +1,87 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Http; + +use Throwable; +use Webman\App; +use function filemtime; +use function gmdate; + +/** + * Class Response + * @package Webman\Http + */ +class Response extends \Workerman\Protocols\Http\Response +{ + /** + * @var Throwable + */ + protected $exception = null; + + /** + * File + * @param string $file + * @return $this + */ + public function file(string $file): Response + { + if ($this->notModifiedSince($file)) { + return $this->withStatus(304); + } + return $this->withFile($file); + } + + /** + * Download + * @param string $file + * @param string $downloadName + * @return $this + */ + public function download(string $file, string $downloadName = ''): Response + { + $this->withFile($file); + if ($downloadName) { + $this->header('Content-Disposition', "attachment; filename=\"$downloadName\""); + } + return $this; + } + + /** + * NotModifiedSince + * @param string $file + * @return bool + */ + protected function notModifiedSince(string $file): bool + { + $ifModifiedSince = App::request()->header('if-modified-since'); + if ($ifModifiedSince === null || !is_file($file) || !($mtime = filemtime($file))) { + return false; + } + return $ifModifiedSince === gmdate('D, d M Y H:i:s', $mtime) . ' GMT'; + } + + /** + * Exception + * @param Throwable|null $exception + * @return Throwable|null + */ + public function exception(Throwable $exception = null): ?Throwable + { + if ($exception) { + $this->exception = $exception; + } + return $this->exception; + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/Http/UploadFile.php b/cacme/vendor/workerman/webman-framework/src/Http/UploadFile.php new file mode 100644 index 0000000..8a63421 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Http/UploadFile.php @@ -0,0 +1,111 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Http; + +use Webman\File; +use function pathinfo; + +/** + * Class UploadFile + * @package Webman\Http + */ +class UploadFile extends File +{ + /** + * @var string + */ + protected $uploadName = null; + + /** + * @var string + */ + protected $uploadMimeType = null; + + /** + * @var int + */ + protected $uploadErrorCode = null; + + /** + * UploadFile constructor. + * + * @param string $fileName + * @param string $uploadName + * @param string $uploadMimeType + * @param int $uploadErrorCode + */ + public function __construct(string $fileName, string $uploadName, string $uploadMimeType, int $uploadErrorCode) + { + $this->uploadName = $uploadName; + $this->uploadMimeType = $uploadMimeType; + $this->uploadErrorCode = $uploadErrorCode; + parent::__construct($fileName); + } + + /** + * GetUploadName + * @return string + */ + public function getUploadName(): ?string + { + return $this->uploadName; + } + + /** + * GetUploadMimeType + * @return string + */ + public function getUploadMimeType(): ?string + { + return $this->uploadMimeType; + } + + /** + * GetUploadExtension + * @return string + */ + public function getUploadExtension(): string + { + return pathinfo($this->uploadName, PATHINFO_EXTENSION); + } + + /** + * GetUploadErrorCode + * @return int + */ + public function getUploadErrorCode(): ?int + { + return $this->uploadErrorCode; + } + + /** + * IsValid + * @return bool + */ + public function isValid(): bool + { + return $this->uploadErrorCode === UPLOAD_ERR_OK; + } + + /** + * GetUploadMineType + * @return string + * @deprecated + */ + public function getUploadMineType(): ?string + { + return $this->uploadMimeType; + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/Install.php b/cacme/vendor/workerman/webman-framework/src/Install.php new file mode 100644 index 0000000..cc02c4c --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Install.php @@ -0,0 +1,59 @@ + 'start.php', + 'windows.php' => 'windows.php', + 'support/bootstrap.php' => 'support/bootstrap.php', + 'support/helpers.php' => 'support/helpers.php', + ]; + + /** + * Install + * @return void + */ + public static function install() + { + static::installByRelation(); + } + + /** + * Uninstall + * @return void + */ + public static function uninstall() + { + + } + + /** + * InstallByRelation + * @return void + */ + public static function installByRelation() + { + foreach (static::$pathRelation as $source => $dest) { + if ($pos = strrpos($dest, '/')) { + $parentDir = base_path() . '/' . substr($dest, 0, $pos); + if (!is_dir($parentDir)) { + mkdir($parentDir, 0777, true); + } + } + $sourceFile = __DIR__ . "/$source"; + copy_dir($sourceFile, base_path() . "/$dest", true); + echo "Create $dest\r\n"; + if (is_file($sourceFile)) { + @unlink($sourceFile); + } + } + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Middleware.php b/cacme/vendor/workerman/webman-framework/src/Middleware.php new file mode 100644 index 0000000..57bf133 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Middleware.php @@ -0,0 +1,90 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + + +use RuntimeException; +use function array_merge; +use function array_reverse; +use function is_array; +use function method_exists; + +class Middleware +{ + + /** + * @var array + */ + protected static $instances = []; + + /** + * @param mixed $allMiddlewares + * @param string $plugin + * @return void + */ + public static function load($allMiddlewares, string $plugin = '') + { + if (!is_array($allMiddlewares)) { + return; + } + foreach ($allMiddlewares as $appName => $middlewares) { + if (!is_array($middlewares)) { + throw new RuntimeException('Bad middleware config'); + } + if ($appName === '@') { + $plugin = ''; + } + if (strpos($appName, 'plugin.') !== false) { + $explode = explode('.', $appName, 4); + $plugin = $explode[1]; + $appName = $explode[2] ?? ''; + } + foreach ($middlewares as $className) { + if (method_exists($className, 'process')) { + static::$instances[$plugin][$appName][] = [$className, 'process']; + } else { + // @todo Log + echo "middleware $className::process not exsits\n"; + } + } + } + } + + /** + * @param string $plugin + * @param string $appName + * @param bool $withGlobalMiddleware + * @return array|mixed + */ + public static function getMiddleware(string $plugin, string $appName, bool $withGlobalMiddleware = true) + { + $globalMiddleware = static::$instances['']['@'] ?? []; + $appGlobalMiddleware = $withGlobalMiddleware && isset(static::$instances[$plugin]['']) ? static::$instances[$plugin][''] : []; + if ($appName === '') { + return array_reverse(array_merge($globalMiddleware, $appGlobalMiddleware)); + } + $appMiddleware = static::$instances[$plugin][$appName] ?? []; + return array_reverse(array_merge($globalMiddleware, $appGlobalMiddleware, $appMiddleware)); + } + + /** + * @return void + * @deprecated + */ + public static function container($_) + { + + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/MiddlewareInterface.php b/cacme/vendor/workerman/webman-framework/src/MiddlewareInterface.php new file mode 100644 index 0000000..47c6d51 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/MiddlewareInterface.php @@ -0,0 +1,30 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use Webman\Http\Request; +use Webman\Http\Response; + +interface MiddlewareInterface +{ + /** + * Process an incoming server request. + * + * Processes an incoming server request in order to produce a response. + * If unable to produce the response itself, it may delegate to the provided + * request handler to do so. + */ + public function process(Request $request, callable $handler): Response; +} diff --git a/cacme/vendor/workerman/webman-framework/src/Route.php b/cacme/vendor/workerman/webman-framework/src/Route.php new file mode 100644 index 0000000..87d7a70 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Route.php @@ -0,0 +1,470 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use FastRoute\Dispatcher\GroupCountBased; +use FastRoute\RouteCollector; +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use Webman\Route\Route as RouteObject; +use function array_diff; +use function array_values; +use function class_exists; +use function explode; +use function FastRoute\simpleDispatcher; +use function in_array; +use function is_array; +use function is_callable; +use function is_file; +use function is_scalar; +use function is_string; +use function json_encode; +use function method_exists; +use function strpos; + +/** + * Class Route + * @package Webman + */ +class Route +{ + /** + * @var Route + */ + protected static $instance = null; + + /** + * @var GroupCountBased + */ + protected static $dispatcher = null; + + /** + * @var RouteCollector + */ + protected static $collector = null; + + /** + * @var null|callable + */ + protected static $fallback = []; + + /** + * @var array + */ + protected static $nameList = []; + + /** + * @var string + */ + protected static $groupPrefix = ''; + + /** + * @var bool + */ + protected static $disableDefaultRoute = []; + + /** + * @var RouteObject[] + */ + protected static $allRoutes = []; + + /** + * @var RouteObject[] + */ + protected $routes = []; + + /** + * @var Route[] + */ + protected $children = []; + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function get(string $path, $callback): RouteObject + { + return static::addRoute('GET', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function post(string $path, $callback): RouteObject + { + return static::addRoute('POST', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function put(string $path, $callback): RouteObject + { + return static::addRoute('PUT', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function patch(string $path, $callback): RouteObject + { + return static::addRoute('PATCH', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function delete(string $path, $callback): RouteObject + { + return static::addRoute('DELETE', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function head(string $path, $callback): RouteObject + { + return static::addRoute('HEAD', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function options(string $path, $callback): RouteObject + { + return static::addRoute('OPTIONS', $path, $callback); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function any(string $path, $callback): RouteObject + { + return static::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $path, $callback); + } + + /** + * @param $method + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + public static function add($method, string $path, $callback): RouteObject + { + return static::addRoute($method, $path, $callback); + } + + /** + * @param string|callable $path + * @param callable|null $callback + * @return static + */ + public static function group($path, callable $callback = null): Route + { + if ($callback === null) { + $callback = $path; + $path = ''; + } + $previousGroupPrefix = static::$groupPrefix; + static::$groupPrefix = $previousGroupPrefix . $path; + $previousInstance = static::$instance; + $instance = static::$instance = new static; + static::$collector->addGroup($path, $callback); + static::$groupPrefix = $previousGroupPrefix; + static::$instance = $previousInstance; + if ($previousInstance) { + $previousInstance->addChild($instance); + } + return $instance; + } + + /** + * @param string $name + * @param string $controller + * @param array $options + * @return void + */ + public static function resource(string $name, string $controller, array $options = []) + { + $name = trim($name, '/'); + if (is_array($options) && !empty($options)) { + $diffOptions = array_diff($options, ['index', 'create', 'store', 'update', 'show', 'edit', 'destroy', 'recovery']); + if (!empty($diffOptions)) { + foreach ($diffOptions as $action) { + static::any("/$name/{$action}[/{id}]", [$controller, $action])->name("$name.{$action}"); + } + } + // 注册路由 由于顺序不同会导致路由无效 因此不适用循环注册 + if (in_array('index', $options)) static::get("/$name", [$controller, 'index'])->name("$name.index"); + if (in_array('create', $options)) static::get("/$name/create", [$controller, 'create'])->name("$name.create"); + if (in_array('store', $options)) static::post("/$name", [$controller, 'store'])->name("$name.store"); + if (in_array('update', $options)) static::put("/$name/{id}", [$controller, 'update'])->name("$name.update"); + if (in_array('show', $options)) static::get("/$name/{id}", [$controller, 'show'])->name("$name.show"); + if (in_array('edit', $options)) static::get("/$name/{id}/edit", [$controller, 'edit'])->name("$name.edit"); + if (in_array('destroy', $options)) static::delete("/$name/{id}", [$controller, 'destroy'])->name("$name.destroy"); + if (in_array('recovery', $options)) static::put("/$name/{id}/recovery", [$controller, 'recovery'])->name("$name.recovery"); + } else { + //为空时自动注册所有常用路由 + if (method_exists($controller, 'index')) static::get("/$name", [$controller, 'index'])->name("$name.index"); + if (method_exists($controller, 'create')) static::get("/$name/create", [$controller, 'create'])->name("$name.create"); + if (method_exists($controller, 'store')) static::post("/$name", [$controller, 'store'])->name("$name.store"); + if (method_exists($controller, 'update')) static::put("/$name/{id}", [$controller, 'update'])->name("$name.update"); + if (method_exists($controller, 'show')) static::get("/$name/{id}", [$controller, 'show'])->name("$name.show"); + if (method_exists($controller, 'edit')) static::get("/$name/{id}/edit", [$controller, 'edit'])->name("$name.edit"); + if (method_exists($controller, 'destroy')) static::delete("/$name/{id}", [$controller, 'destroy'])->name("$name.destroy"); + if (method_exists($controller, 'recovery')) static::put("/$name/{id}/recovery", [$controller, 'recovery'])->name("$name.recovery"); + } + } + + /** + * @return RouteObject[] + */ + public static function getRoutes(): array + { + return static::$allRoutes; + } + + /** + * disableDefaultRoute. + * + * @return void + */ + public static function disableDefaultRoute($plugin = '') + { + static::$disableDefaultRoute[$plugin] = true; + } + + /** + * @param string $plugin + * @return bool + */ + public static function hasDisableDefaultRoute(string $plugin = ''): bool + { + return static::$disableDefaultRoute[$plugin] ?? false; + } + + /** + * @param $middleware + * @return $this + */ + public function middleware($middleware): Route + { + foreach ($this->routes as $route) { + $route->middleware($middleware); + } + foreach ($this->getChildren() as $child) { + $child->middleware($middleware); + } + return $this; + } + + /** + * @param RouteObject $route + */ + public function collect(RouteObject $route) + { + $this->routes[] = $route; + } + + /** + * @param string $name + * @param RouteObject $instance + */ + public static function setByName(string $name, RouteObject $instance) + { + static::$nameList[$name] = $instance; + } + + /** + * @param string $name + * @return null|RouteObject + */ + public static function getByName(string $name): ?RouteObject + { + return static::$nameList[$name] ?? null; + } + + /** + * @param Route $route + * @return void + */ + public function addChild(Route $route) + { + $this->children[] = $route; + } + + /** + * @return Route[] + */ + public function getChildren() + { + return $this->children; + } + + /** + * @param string $method + * @param string $path + * @return array + */ + public static function dispatch(string $method, string $path): array + { + return static::$dispatcher->dispatch($method, $path); + } + + /** + * @param string $path + * @param callable|mixed $callback + * @return callable|false|string[] + */ + public static function convertToCallable(string $path, $callback) + { + if (is_string($callback) && strpos($callback, '@')) { + $callback = explode('@', $callback, 2); + } + + if (!is_array($callback)) { + if (!is_callable($callback)) { + $callStr = is_scalar($callback) ? $callback : 'Closure'; + echo "Route $path $callStr is not callable\n"; + return false; + } + } else { + $callback = array_values($callback); + if (!isset($callback[1]) || !class_exists($callback[0]) || !method_exists($callback[0], $callback[1])) { + echo "Route $path " . json_encode($callback) . " is not callable\n"; + return false; + } + } + + return $callback; + } + + /** + * @param array|string $methods + * @param string $path + * @param callable|mixed $callback + * @return RouteObject + */ + protected static function addRoute($methods, string $path, $callback): RouteObject + { + $route = new RouteObject($methods, static::$groupPrefix . $path, $callback); + static::$allRoutes[] = $route; + + if ($callback = static::convertToCallable($path, $callback)) { + static::$collector->addRoute($methods, $path, ['callback' => $callback, 'route' => $route]); + } + if (static::$instance) { + static::$instance->collect($route); + } + return $route; + } + + /** + * Load. + * @param mixed $paths + * @return void + */ + public static function load($paths) + { + if (!is_array($paths)) { + return; + } + static::$dispatcher = simpleDispatcher(function (RouteCollector $route) use ($paths) { + Route::setCollector($route); + foreach ($paths as $configPath) { + $routeConfigFile = $configPath . '/route.php'; + if (is_file($routeConfigFile)) { + require_once $routeConfigFile; + } + if (!is_dir($pluginConfigPath = $configPath . '/plugin')) { + continue; + } + $dirIterator = new RecursiveDirectoryIterator($pluginConfigPath, FilesystemIterator::FOLLOW_SYMLINKS); + $iterator = new RecursiveIteratorIterator($dirIterator); + foreach ($iterator as $file) { + if ($file->getBaseName('.php') !== 'route') { + continue; + } + $appConfigFile = pathinfo($file, PATHINFO_DIRNAME) . '/app.php'; + if (!is_file($appConfigFile)) { + continue; + } + $appConfig = include $appConfigFile; + if (empty($appConfig['enable'])) { + continue; + } + require_once $file; + } + } + }); + } + + /** + * SetCollector. + * @param RouteCollector $route + * @return void + */ + public static function setCollector(RouteCollector $route) + { + static::$collector = $route; + } + + /** + * Fallback. + * @param callable|mixed $callback + * @param string $plugin + * @return void + */ + public static function fallback(callable $callback, string $plugin = '') + { + static::$fallback[$plugin] = $callback; + } + + /** + * GetFallBack. + * @param string $plugin + * @return callable|null + */ + public static function getFallback(string $plugin = ''): ?callable + { + return static::$fallback[$plugin] ?? null; + } + + /** + * @return void + * @deprecated + */ + public static function container() + { + + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Route/Route.php b/cacme/vendor/workerman/webman-framework/src/Route/Route.php new file mode 100644 index 0000000..a65e7b8 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Route/Route.php @@ -0,0 +1,199 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Route; + +use Webman\Route as Router; +use function array_merge; +use function count; +use function preg_replace_callback; +use function str_replace; + +/** + * Class Route + * @package Webman + */ +class Route +{ + /** + * @var string|null + */ + protected $name = null; + + /** + * @var array + */ + protected $methods = []; + + /** + * @var string + */ + protected $path = ''; + + /** + * @var callable + */ + protected $callback = null; + + /** + * @var array + */ + protected $middlewares = []; + + /** + * @var array + */ + protected $params = []; + + /** + * Route constructor. + * @param array $methods + * @param string $path + * @param callable $callback + */ + public function __construct($methods, string $path, $callback) + { + $this->methods = (array)$methods; + $this->path = $path; + $this->callback = $callback; + } + + /** + * Get name. + * @return string|null + */ + public function getName(): ?string + { + return $this->name ?? null; + } + + /** + * Name. + * @param string $name + * @return $this + */ + public function name(string $name): Route + { + $this->name = $name; + Router::setByName($name, $this); + return $this; + } + + /** + * Middleware. + * @param mixed $middleware + * @return $this|array + */ + public function middleware($middleware = null) + { + if ($middleware === null) { + return $this->middlewares; + } + $this->middlewares = array_merge($this->middlewares, is_array($middleware) ? array_reverse($middleware) : [$middleware]); + return $this; + } + + /** + * GetPath. + * @return string + */ + public function getPath(): string + { + return $this->path; + } + + /** + * GetMethods. + * @return array + */ + public function getMethods(): array + { + return $this->methods; + } + + /** + * GetCallback. + * @return callable|null + */ + public function getCallback() + { + return $this->callback; + } + + /** + * GetMiddleware. + * @return array + */ + public function getMiddleware(): array + { + return $this->middlewares; + } + + /** + * Param. + * @param string|null $name + * @param $default + * @return array|mixed|null + */ + public function param(string $name = null, $default = null) + { + if ($name === null) { + return $this->params; + } + return $this->params[$name] ?? $default; + } + + /** + * SetParams. + * @param array $params + * @return $this + */ + public function setParams(array $params): Route + { + $this->params = array_merge($this->params, $params); + return $this; + } + + /** + * Url. + * @param array $parameters + * @return string + */ + public function url(array $parameters = []): string + { + if (empty($parameters)) { + return $this->path; + } + $path = str_replace(['[', ']'], '', $this->path); + $path = preg_replace_callback('/\{(.*?)(?:\:[^\}]*?)*?\}/', function ($matches) use (&$parameters) { + if (!$parameters) { + return $matches[0]; + } + if (isset($parameters[$matches[1]])) { + $value = $parameters[$matches[1]]; + unset($parameters[$matches[1]]); + return $value; + } + $key = key($parameters); + if (is_int($key)) { + $value = $parameters[$key]; + unset($parameters[$key]); + return $value; + } + return $matches[0]; + }, $path); + return count($parameters) > 0 ? $path . '?' . http_build_query($parameters) : $path; + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Session/FileSessionHandler.php b/cacme/vendor/workerman/webman-framework/src/Session/FileSessionHandler.php new file mode 100644 index 0000000..10fda70 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Session/FileSessionHandler.php @@ -0,0 +1,26 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Session; + +use Workerman\Protocols\Http\Session\FileSessionHandler as FileHandler; + +/** + * Class FileSessionHandler + * @package Webman + */ +class FileSessionHandler extends FileHandler +{ + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Session/RedisClusterSessionHandler.php b/cacme/vendor/workerman/webman-framework/src/Session/RedisClusterSessionHandler.php new file mode 100644 index 0000000..c00efae --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Session/RedisClusterSessionHandler.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Session; + +use Workerman\Protocols\Http\Session\RedisClusterSessionHandler as RedisClusterHandler; + +class RedisClusterSessionHandler extends RedisClusterHandler +{ + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Session/RedisSessionHandler.php b/cacme/vendor/workerman/webman-framework/src/Session/RedisSessionHandler.php new file mode 100644 index 0000000..c124cbd --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Session/RedisSessionHandler.php @@ -0,0 +1,26 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman\Session; + +use Workerman\Protocols\Http\Session\RedisSessionHandler as RedisHandler; + +/** + * Class FileSessionHandler + * @package Webman + */ +class RedisSessionHandler extends RedisHandler +{ + +} diff --git a/cacme/vendor/workerman/webman-framework/src/Util.php b/cacme/vendor/workerman/webman-framework/src/Util.php new file mode 100644 index 0000000..0a19632 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/Util.php @@ -0,0 +1,44 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +use function array_diff; +use function array_map; +use function scandir; + +/** + * Class Util + * @package Webman + */ +class Util +{ + /** + * ScanDir. + * @param string $basePath + * @param bool $withBasePath + * @return array + */ + public static function scanDir(string $basePath, bool $withBasePath = true): array + { + if (!is_dir($basePath)) { + return []; + } + $paths = array_diff(scandir($basePath), array('.', '..')) ?: []; + return $withBasePath ? array_map(static function ($path) use ($basePath) { + return $basePath . DIRECTORY_SEPARATOR . $path; + }, $paths) : $paths; + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/View.php b/cacme/vendor/workerman/webman-framework/src/View.php new file mode 100644 index 0000000..b50cee0 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/View.php @@ -0,0 +1,27 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Webman; + +interface View +{ + /** + * Render. + * @param string $template + * @param array $vars + * @param string|null $app + * @return string + */ + public static function render(string $template, array $vars, string $app = null): string; +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/App.php b/cacme/vendor/workerman/webman-framework/src/support/App.php new file mode 100644 index 0000000..53619dd --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/App.php @@ -0,0 +1,151 @@ +load(); + } else { + Dotenv::createMutable(run_path())->load(); + } + } + + static::loadAllConfig(['route', 'container']); + + $errorReporting = config('app.error_reporting'); + if (isset($errorReporting)) { + error_reporting($errorReporting); + } + if ($timezone = config('app.default_timezone')) { + date_default_timezone_set($timezone); + } + + $runtimeLogsPath = runtime_path() . DIRECTORY_SEPARATOR . 'logs'; + if (!file_exists($runtimeLogsPath) || !is_dir($runtimeLogsPath)) { + if (!mkdir($runtimeLogsPath, 0777, true)) { + throw new RuntimeException("Failed to create runtime logs directory. Please check the permission."); + } + } + + $runtimeViewsPath = runtime_path() . DIRECTORY_SEPARATOR . 'views'; + if (!file_exists($runtimeViewsPath) || !is_dir($runtimeViewsPath)) { + if (!mkdir($runtimeViewsPath, 0777, true)) { + throw new RuntimeException("Failed to create runtime views directory. Please check the permission."); + } + } + + Worker::$onMasterReload = function () { + if (function_exists('opcache_get_status')) { + if ($status = opcache_get_status()) { + if (isset($status['scripts']) && $scripts = $status['scripts']) { + foreach (array_keys($scripts) as $file) { + opcache_invalidate($file, true); + } + } + } + } + }; + + $config = config('server'); + Worker::$pidFile = $config['pid_file']; + Worker::$stdoutFile = $config['stdout_file']; + Worker::$logFile = $config['log_file']; + Worker::$eventLoopClass = $config['event_loop'] ?? ''; + TcpConnection::$defaultMaxPackageSize = $config['max_package_size'] ?? 10 * 1024 * 1024; + if (property_exists(Worker::class, 'statusFile')) { + Worker::$statusFile = $config['status_file'] ?? ''; + } + if (property_exists(Worker::class, 'stopTimeout')) { + Worker::$stopTimeout = $config['stop_timeout'] ?? 2; + } + + if ($config['listen']) { + $worker = new Worker($config['listen'], $config['context']); + $propertyMap = [ + 'name', + 'count', + 'user', + 'group', + 'reusePort', + 'transport', + 'protocol' + ]; + foreach ($propertyMap as $property) { + if (isset($config[$property])) { + $worker->$property = $config[$property]; + } + } + + $worker->onWorkerStart = function ($worker) { + require_once base_path() . '/support/bootstrap.php'; + $app = new \Webman\App(config('app.request_class', Request::class), Log::channel('default'), app_path(), public_path()); + $worker->onMessage = [$app, 'onMessage']; + call_user_func([$app, 'onWorkerStart'], $worker); + }; + } + + // Windows does not support custom processes. + if (DIRECTORY_SEPARATOR === '/') { + foreach (config('process', []) as $processName => $config) { + worker_start($processName, $config); + } + foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['process'] ?? [] as $processName => $config) { + worker_start("plugin.$firm.$name.$processName", $config); + } + } + foreach ($projects['process'] ?? [] as $processName => $config) { + worker_start("plugin.$firm.$processName", $config); + } + } + } + + Worker::runAll(); + } + + /** + * LoadAllConfig. + * @param array $excludes + * @return void + */ + public static function loadAllConfig(array $excludes = []) + { + Config::load(config_path(), $excludes); + $directory = base_path() . '/plugin'; + foreach (Util::scanDir($directory, false) as $name) { + $dir = "$directory/$name/config"; + if (is_dir($dir)) { + Config::load($dir, $excludes, "plugin.$name"); + } + } + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Cache.php b/cacme/vendor/workerman/webman-framework/src/support/Cache.php new file mode 100644 index 0000000..8cf5a44 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Cache.php @@ -0,0 +1,50 @@ +client()); + self::$instance = new Psr16Cache($adapter); + } + return static::$instance; + } + + /** + * @param $name + * @param $arguments + * @return mixed + */ + public static function __callStatic($name, $arguments) + { + return static::instance()->{$name}(... $arguments); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Container.php b/cacme/vendor/workerman/webman-framework/src/support/Container.php new file mode 100644 index 0000000..c3734c7 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Container.php @@ -0,0 +1,48 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use Webman\Config; + +/** + * Class Container + * @package support + * @method static mixed get($name) + * @method static mixed make($name, array $parameters) + * @method static bool has($name) + */ +class Container +{ + /** + * Instance + * @param string $plugin + * @return array|mixed|void|null + */ + public static function instance(string $plugin = '') + { + return Config::get($plugin ? "plugin.$plugin.container" : 'container'); + } + + /** + * @param string $name + * @param array $arguments + * @return mixed + */ + public static function __callStatic(string $name, array $arguments) + { + $plugin = \Webman\App::getPluginByClass($name); + return static::instance($plugin)->{$name}(... $arguments); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Context.php b/cacme/vendor/workerman/webman-framework/src/support/Context.php new file mode 100644 index 0000000..7a8348b --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Context.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +/** + * Class Context + * @package Webman + */ +class Context extends \Webman\Context +{ + +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Db.php b/cacme/vendor/workerman/webman-framework/src/support/Db.php new file mode 100644 index 0000000..2bce62f --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Db.php @@ -0,0 +1,36 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use Closure; +use Illuminate\Database\Capsule\Manager; + +/** + * Class Db + * @package support + * @method static array select(string $query, $bindings = [], $useReadPdo = true) + * @method static int insert(string $query, $bindings = []) + * @method static int update(string $query, $bindings = []) + * @method static int delete(string $query, $bindings = []) + * @method static bool statement(string $query, $bindings = []) + * @method static mixed transaction(Closure $callback, $attempts = 1) + * @method static void beginTransaction() + * @method static void rollBack($toLevel = null) + * @method static void commit() + */ +class Db extends Manager +{ + +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/support/Log.php b/cacme/vendor/workerman/webman-framework/src/support/Log.php new file mode 100644 index 0000000..11512de --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Log.php @@ -0,0 +1,139 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Handler\FormattableHandlerInterface; +use Monolog\Handler\HandlerInterface; +use Monolog\Logger; +use function array_values; +use function config; +use function is_array; + +/** + * Class Log + * @package support + * + * @method static void log($level, $message, array $context = []) + * @method static void debug($message, array $context = []) + * @method static void info($message, array $context = []) + * @method static void notice($message, array $context = []) + * @method static void warning($message, array $context = []) + * @method static void error($message, array $context = []) + * @method static void critical($message, array $context = []) + * @method static void alert($message, array $context = []) + * @method static void emergency($message, array $context = []) + */ +class Log +{ + /** + * @var array + */ + protected static $instance = []; + + /** + * Channel. + * @param string $name + * @return Logger + */ + public static function channel(string $name = 'default'): Logger + { + if (!isset(static::$instance[$name])) { + $config = config('log', [])[$name]; + $handlers = self::handlers($config); + $processors = self::processors($config); + static::$instance[$name] = new Logger($name, $handlers, $processors); + } + return static::$instance[$name]; + } + + /** + * Handlers. + * @param array $config + * @return array + */ + protected static function handlers(array $config): array + { + $handlerConfigs = $config['handlers'] ?? [[]]; + $handlers = []; + foreach ($handlerConfigs as $value) { + $class = $value['class'] ?? []; + $constructor = $value['constructor'] ?? []; + + $formatterConfig = $value['formatter'] ?? []; + + $class && $handlers[] = self::handler($class, $constructor, $formatterConfig); + } + + return $handlers; + } + + /** + * Handler. + * @param string $class + * @param array $constructor + * @param array $formatterConfig + * @return HandlerInterface + */ + protected static function handler(string $class, array $constructor, array $formatterConfig): HandlerInterface + { + /** @var HandlerInterface $handler */ + $handler = new $class(... array_values($constructor)); + + if ($handler instanceof FormattableHandlerInterface && $formatterConfig) { + $formatterClass = $formatterConfig['class']; + $formatterConstructor = $formatterConfig['constructor']; + + /** @var FormatterInterface $formatter */ + $formatter = new $formatterClass(... array_values($formatterConstructor)); + + $handler->setFormatter($formatter); + } + + return $handler; + } + + /** + * Processors. + * @param array $config + * @return array + */ + protected static function processors(array $config): array + { + $result = []; + if (!isset($config['processors']) && isset($config['processor'])) { + $config['processors'] = [$config['processor']]; + } + + foreach ($config['processors'] ?? [] as $value) { + if (is_array($value) && isset($value['class'])) { + $value = new $value['class'](... array_values($value['constructor'] ?? [])); + } + $result[] = $value; + } + + return $result; + } + + /** + * @param string $name + * @param array $arguments + * @return mixed + */ + public static function __callStatic(string $name, array $arguments) + { + return static::channel()->{$name}(... $arguments); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Model.php b/cacme/vendor/workerman/webman-framework/src/support/Model.php new file mode 100644 index 0000000..dbbedf4 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Model.php @@ -0,0 +1,262 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use Closure; +use Illuminate\Contracts\Pagination\CursorPaginator; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use Illuminate\Contracts\Pagination\Paginator; +use Illuminate\Database\Eloquent\Model as BaseModel; +use Illuminate\Database\Query\Builder; +use Illuminate\Database\Query\Expression; +use Illuminate\Database\Query\Grammars\Grammar; +use Illuminate\Database\Query\Processors\Processor; +use Illuminate\Support\Collection; +use Illuminate\Support\LazyCollection; + +/** + * @method static BaseModel make($attributes = []) + * @method static \Illuminate\Database\Eloquent\Builder withGlobalScope($identifier, $scope) + * @method static \Illuminate\Database\Eloquent\Builder withoutGlobalScope($scope) + * @method static \Illuminate\Database\Eloquent\Builder withoutGlobalScopes($scopes = null) + * @method static array removedScopes() + * @method static \Illuminate\Database\Eloquent\Builder whereKey($id) + * @method static \Illuminate\Database\Eloquent\Builder whereKeyNot($id) + * @method static \Illuminate\Database\Eloquent\Builder where($column, $operator = null, $value = null, $boolean = 'and') + * @method static BaseModel|null firstWhere($column, $operator = null, $value = null, $boolean = 'and') + * @method static \Illuminate\Database\Eloquent\Builder orWhere($column, $operator = null, $value = null) + * @method static \Illuminate\Database\Eloquent\Builder latest($column = null) + * @method static \Illuminate\Database\Eloquent\Builder oldest($column = null) + * @method static \Illuminate\Database\Eloquent\Collection hydrate($items) + * @method static \Illuminate\Database\Eloquent\Collection fromQuery($query, $bindings = []) + * @method static BaseModel|\Illuminate\Database\Eloquent\Collection|static[]|static|null find($id, $columns = []) + * @method static \Illuminate\Database\Eloquent\Collection findMany($ids, $columns = []) + * @method static BaseModel|\Illuminate\Database\Eloquent\Collection|static|static[] findOrFail($id, $columns = []) + * @method static BaseModel|static findOrNew($id, $columns = []) + * @method static BaseModel|static firstOrNew($attributes = [], $values = []) + * @method static BaseModel|static firstOrCreate($attributes = [], $values = []) + * @method static BaseModel|static updateOrCreate($attributes, $values = []) + * @method static BaseModel|static firstOrFail($columns = []) + * @method static BaseModel|static|mixed firstOr($columns = [], $callback = null) + * @method static BaseModel sole($columns = []) + * @method static mixed value($column) + * @method static \Illuminate\Database\Eloquent\Collection[]|static[] get($columns = []) + * @method static BaseModel[]|static[] getModels($columns = []) + * @method static array eagerLoadRelations($models) + * @method static LazyCollection cursor() + * @method static Collection pluck($column, $key = null) + * @method static LengthAwarePaginator paginate($perPage = null, $columns = [], $pageName = 'page', $page = null) + * @method static Paginator simplePaginate($perPage = null, $columns = [], $pageName = 'page', $page = null) + * @method static CursorPaginator cursorPaginate($perPage = null, $columns = [], $cursorName = 'cursor', $cursor = null) + * @method static BaseModel|$this create($attributes = []) + * @method static BaseModel|$this forceCreate($attributes) + * @method static int upsert($values, $uniqueBy, $update = null) + * @method static void onDelete($callback) + * @method static static|mixed scopes($scopes) + * @method static static applyScopes() + * @method static \Illuminate\Database\Eloquent\Builder without($relations) + * @method static \Illuminate\Database\Eloquent\Builder withOnly($relations) + * @method static BaseModel newModelInstance($attributes = []) + * @method static \Illuminate\Database\Eloquent\Builder withCasts($casts) + * @method static Builder getQuery() + * @method static \Illuminate\Database\Eloquent\Builder setQuery($query) + * @method static Builder toBase() + * @method static array getEagerLoads() + * @method static \Illuminate\Database\Eloquent\Builder setEagerLoads($eagerLoad) + * @method static BaseModel getModel() + * @method static \Illuminate\Database\Eloquent\Builder setModel($model) + * @method static Closure getMacro($name) + * @method static bool hasMacro($name) + * @method static Closure getGlobalMacro($name) + * @method static bool hasGlobalMacro($name) + * @method static static clone () + * @method static \Illuminate\Database\Eloquent\Builder has($relation, $operator = '>=', $count = 1, $boolean = 'and', $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder orHas($relation, $operator = '>=', $count = 1) + * @method static \Illuminate\Database\Eloquent\Builder doesntHave($relation, $boolean = 'and', $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder orDoesntHave($relation) + * @method static \Illuminate\Database\Eloquent\Builder whereHas($relation, $callback = null, $operator = '>=', $count = 1) + * @method static \Illuminate\Database\Eloquent\Builder orWhereHas($relation, $callback = null, $operator = '>=', $count = 1) + * @method static \Illuminate\Database\Eloquent\Builder whereDoesntHave($relation, $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder orWhereDoesntHave($relation, $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder hasMorph($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder orHasMorph($relation, $types, $operator = '>=', $count = 1) + * @method static \Illuminate\Database\Eloquent\Builder doesntHaveMorph($relation, $types, $boolean = 'and', $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder orDoesntHaveMorph($relation, $types) + * @method static \Illuminate\Database\Eloquent\Builder whereHasMorph($relation, $types, $callback = null, $operator = '>=', $count = 1) + * @method static \Illuminate\Database\Eloquent\Builder orWhereHasMorph($relation, $types, $callback = null, $operator = '>=', $count = 1) + * @method static \Illuminate\Database\Eloquent\Builder whereDoesntHaveMorph($relation, $types, $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder orWhereDoesntHaveMorph($relation, $types, $callback = null) + * @method static \Illuminate\Database\Eloquent\Builder withAggregate($relations, $column, $function = null) + * @method static \Illuminate\Database\Eloquent\Builder withCount($relations) + * @method static \Illuminate\Database\Eloquent\Builder withMax($relation, $column) + * @method static \Illuminate\Database\Eloquent\Builder withMin($relation, $column) + * @method static \Illuminate\Database\Eloquent\Builder withSum($relation, $column) + * @method static \Illuminate\Database\Eloquent\Builder withAvg($relation, $column) + * @method static \Illuminate\Database\Eloquent\Builder withExists($relation) + * @method static \Illuminate\Database\Eloquent\Builder mergeConstraintsFrom($from) + * @method static Collection explain() + * @method static bool chunk($count, $callback) + * @method static Collection chunkMap($callback, $count = 1000) + * @method static bool each($callback, $count = 1000) + * @method static bool chunkById($count, $callback, $column = null, $alias = null) + * @method static bool eachById($callback, $count = 1000, $column = null, $alias = null) + * @method static LazyCollection lazy($chunkSize = 1000) + * @method static LazyCollection lazyById($chunkSize = 1000, $column = null, $alias = null) + * @method static BaseModel|object|static|null first($columns = []) + * @method static BaseModel|object|null baseSole($columns = []) + * @method static \Illuminate\Database\Eloquent\Builder tap($callback) + * @method static mixed when($value, $callback, $default = null) + * @method static mixed unless($value, $callback, $default = null) + * @method static Builder select($columns = []) + * @method static Builder selectSub($query, $as) + * @method static Builder selectRaw($expression, $bindings = []) + * @method static Builder fromSub($query, $as) + * @method static Builder fromRaw($expression, $bindings = []) + * @method static Builder addSelect($column) + * @method static Builder distinct() + * @method static Builder from($table, $as = null) + * @method static Builder join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false) + * @method static Builder joinWhere($table, $first, $operator, $second, $type = 'inner') + * @method static Builder joinSub($query, $as, $first, $operator = null, $second = null, $type = 'inner', $where = false) + * @method static Builder leftJoin($table, $first, $operator = null, $second = null) + * @method static Builder leftJoinWhere($table, $first, $operator, $second) + * @method static Builder leftJoinSub($query, $as, $first, $operator = null, $second = null) + * @method static Builder rightJoin($table, $first, $operator = null, $second = null) + * @method static Builder rightJoinWhere($table, $first, $operator, $second) + * @method static Builder rightJoinSub($query, $as, $first, $operator = null, $second = null) + * @method static Builder crossJoin($table, $first = null, $operator = null, $second = null) + * @method static Builder crossJoinSub($query, $as) + * @method static void mergeWheres($wheres, $bindings) + * @method static array prepareValueAndOperator($value, $operator, $useDefault = false) + * @method static Builder whereColumn($first, $operator = null, $second = null, $boolean = 'and') + * @method static Builder orWhereColumn($first, $operator = null, $second = null) + * @method static Builder whereRaw($sql, $bindings = [], $boolean = 'and') + * @method static Builder orWhereRaw($sql, $bindings = []) + * @method static Builder whereIn($column, $values, $boolean = 'and', $not = false) + * @method static Builder orWhereIn($column, $values) + * @method static Builder whereNotIn($column, $values, $boolean = 'and') + * @method static Builder orWhereNotIn($column, $values) + * @method static Builder whereIntegerInRaw($column, $values, $boolean = 'and', $not = false) + * @method static Builder orWhereIntegerInRaw($column, $values) + * @method static Builder whereIntegerNotInRaw($column, $values, $boolean = 'and') + * @method static Builder orWhereIntegerNotInRaw($column, $values) + * @method static Builder whereNull($columns, $boolean = 'and', $not = false) + * @method static Builder orWhereNull($column) + * @method static Builder whereNotNull($columns, $boolean = 'and') + * @method static Builder whereBetween($column, $values, $boolean = 'and', $not = false) + * @method static Builder whereBetweenColumns($column, $values, $boolean = 'and', $not = false) + * @method static Builder orWhereBetween($column, $values) + * @method static Builder orWhereBetweenColumns($column, $values) + * @method static Builder whereNotBetween($column, $values, $boolean = 'and') + * @method static Builder whereNotBetweenColumns($column, $values, $boolean = 'and') + * @method static Builder orWhereNotBetween($column, $values) + * @method static Builder orWhereNotBetweenColumns($column, $values) + * @method static Builder orWhereNotNull($column) + * @method static Builder whereDate($column, $operator, $value = null, $boolean = 'and') + * @method static Builder orWhereDate($column, $operator, $value = null) + * @method static Builder whereTime($column, $operator, $value = null, $boolean = 'and') + * @method static Builder orWhereTime($column, $operator, $value = null) + * @method static Builder whereDay($column, $operator, $value = null, $boolean = 'and') + * @method static Builder orWhereDay($column, $operator, $value = null) + * @method static Builder whereMonth($column, $operator, $value = null, $boolean = 'and') + * @method static Builder orWhereMonth($column, $operator, $value = null) + * @method static Builder whereYear($column, $operator, $value = null, $boolean = 'and') + * @method static Builder orWhereYear($column, $operator, $value = null) + * @method static Builder whereNested($callback, $boolean = 'and') + * @method static Builder forNestedWhere() + * @method static Builder addNestedWhereQuery($query, $boolean = 'and') + * @method static Builder whereExists($callback, $boolean = 'and', $not = false) + * @method static Builder orWhereExists($callback, $not = false) + * @method static Builder whereNotExists($callback, $boolean = 'and') + * @method static Builder orWhereNotExists($callback) + * @method static Builder addWhereExistsQuery($query, $boolean = 'and', $not = false) + * @method static Builder whereRowValues($columns, $operator, $values, $boolean = 'and') + * @method static Builder orWhereRowValues($columns, $operator, $values) + * @method static Builder whereJsonContains($column, $value, $boolean = 'and', $not = false) + * @method static Builder orWhereJsonContains($column, $value) + * @method static Builder whereJsonDoesntContain($column, $value, $boolean = 'and') + * @method static Builder orWhereJsonDoesntContain($column, $value) + * @method static Builder whereJsonLength($column, $operator, $value = null, $boolean = 'and') + * @method static Builder orWhereJsonLength($column, $operator, $value = null) + * @method static Builder dynamicWhere($method, $parameters) + * @method static Builder groupBy(...$groups) + * @method static Builder groupByRaw($sql, $bindings = []) + * @method static Builder having($column, $operator = null, $value = null, $boolean = 'and') + * @method static Builder orHaving($column, $operator = null, $value = null) + * @method static Builder havingBetween($column, $values, $boolean = 'and', $not = false) + * @method static Builder havingRaw($sql, $bindings = [], $boolean = 'and') + * @method static Builder orHavingRaw($sql, $bindings = []) + * @method static Builder orderBy($column, $direction = 'asc') + * @method static Builder orderByDesc($column) + * @method static Builder inRandomOrder($seed = '') + * @method static Builder orderByRaw($sql, $bindings = []) + * @method static Builder skip($value) + * @method static Builder offset($value) + * @method static Builder take($value) + * @method static Builder limit($value) + * @method static Builder forPage($page, $perPage = 15) + * @method static Builder forPageBeforeId($perPage = 15, $lastId = 0, $column = 'id') + * @method static Builder forPageAfterId($perPage = 15, $lastId = 0, $column = 'id') + * @method static Builder reorder($column = null, $direction = 'asc') + * @method static Builder union($query, $all = false) + * @method static Builder unionAll($query) + * @method static Builder lock($value = true) + * @method static Builder lockForUpdate() + * @method static Builder sharedLock() + * @method static Builder beforeQuery($callback) + * @method static void applyBeforeQueryCallbacks() + * @method static string toSql() + * @method static int getCountForPagination($columns = []) + * @method static string implode($column, $glue = '') + * @method static bool exists() + * @method static bool doesntExist() + * @method static mixed existsOr($callback) + * @method static mixed doesntExistOr($callback) + * @method static int count($columns = '*') + * @method static mixed min($column) + * @method static mixed max($column) + * @method static mixed sum($column) + * @method static mixed avg($column) + * @method static mixed average($column) + * @method static mixed aggregate($function, $columns = []) + * @method static float|int numericAggregate($function, $columns = []) + * @method static bool insert($values) + * @method static int insertOrIgnore($values) + * @method static int insertGetId($values, $sequence = null) + * @method static int insertUsing($columns, $query) + * @method static bool updateOrInsert($attributes, $values = []) + * @method static void truncate() + * @method static Expression raw($value) + * @method static array getBindings() + * @method static array getRawBindings() + * @method static Builder setBindings($bindings, $type = 'where') + * @method static Builder addBinding($value, $type = 'where') + * @method static Builder mergeBindings($query) + * @method static array cleanBindings($bindings) + * @method static Processor getProcessor() + * @method static Grammar getGrammar() + * @method static Builder useWritePdo() + * @method static static cloneWithout($properties) + * @method static static cloneWithoutBindings($except) + * @method static Builder dump() + * @method static void dd() + * @method static void macro($name, $macro) + * @method static void mixin($mixin, $replace = true) + * @method static mixed macroCall($method, $parameters) + */ +class Model extends BaseModel +{ + +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Plugin.php b/cacme/vendor/workerman/webman-framework/src/support/Plugin.php new file mode 100644 index 0000000..7b296be --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Plugin.php @@ -0,0 +1,108 @@ + $path) { + $pluginConst = "\\{$namespace}Install::WEBMAN_PLUGIN"; + if (!defined($pluginConst)) { + continue; + } + $installFunction = "\\{$namespace}Install::install"; + if (is_callable($installFunction)) { + $installFunction(true); + } + } + } + + /** + * Update. + * @param mixed $event + * @return void + */ + public static function update($event) + { + static::findHelper(); + $psr4 = static::getPsr4($event); + foreach ($psr4 as $namespace => $path) { + $pluginConst = "\\{$namespace}Install::WEBMAN_PLUGIN"; + if (!defined($pluginConst)) { + continue; + } + $updateFunction = "\\{$namespace}Install::update"; + if (is_callable($updateFunction)) { + $updateFunction(); + continue; + } + $installFunction = "\\{$namespace}Install::install"; + if (is_callable($installFunction)) { + $installFunction(false); + } + } + } + + /** + * Uninstall. + * @param mixed $event + * @return void + */ + public static function uninstall($event) + { + static::findHelper(); + $psr4 = static::getPsr4($event); + foreach ($psr4 as $namespace => $path) { + $pluginConst = "\\{$namespace}Install::WEBMAN_PLUGIN"; + if (!defined($pluginConst)) { + continue; + } + $uninstallFunction = "\\{$namespace}Install::uninstall"; + if (is_callable($uninstallFunction)) { + $uninstallFunction(); + } + } + } + + /** + * Get psr-4 info + * + * @param mixed $event + * @return array + */ + protected static function getPsr4($event) + { + $operation = $event->getOperation(); + $autoload = method_exists($operation, 'getPackage') ? $operation->getPackage()->getAutoload() : $operation->getTargetPackage()->getAutoload(); + return $autoload['psr-4'] ?? []; + } + + /** + * FindHelper. + * @return void + */ + protected static function findHelper() + { + // Plugin.php in vendor + $file = __DIR__ . '/../../../../../support/helpers.php'; + if (is_file($file)) { + require_once $file; + return; + } + // Plugin.php in webman + require_once __DIR__ . '/helpers.php'; + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Redis.php b/cacme/vendor/workerman/webman-framework/src/support/Redis.php new file mode 100644 index 0000000..de566c5 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Redis.php @@ -0,0 +1,283 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use Illuminate\Events\Dispatcher; +use Illuminate\Redis\Connections\Connection; +use Illuminate\Redis\RedisManager; +use Workerman\Timer; +use Workerman\Worker; +use function class_exists; +use function config; +use function in_array; + + +/** + * Class Redis + * @package support + * + * Strings methods + * @method static int append($key, $value) + * @method static int bitCount($key) + * @method static int decr($key, $value = 1) + * @method static int decrBy($key, $value) + * @method static string|bool get($key) + * @method static int getBit($key, $offset) + * @method static string getRange($key, $start, $end) + * @method static string getSet($key, $value) + * @method static int incr($key, $value = 1) + * @method static int incrBy($key, $value) + * @method static float incrByFloat($key, $value) + * @method static array mGet(array $keys) + * @method static array getMultiple(array $keys) + * @method static bool mSet($pairs) + * @method static bool mSetNx($pairs) + * @method static bool set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null) + * @method static bool setBit($key, $offset, $value) + * @method static bool setEx($key, $ttl, $value) + * @method static bool pSetEx($key, $ttl, $value) + * @method static bool setNx($key, $value) + * @method static string setRange($key, $offset, $value) + * @method static int strLen($key) + * Keys methods + * @method static int del(...$keys) + * @method static int unlink(...$keys) + * @method static false|string dump($key) + * @method static int exists(...$keys) + * @method static bool expire($key, $ttl) + * @method static bool pexpire($key, $ttl) + * @method static bool expireAt($key, $timestamp) + * @method static bool pexpireAt($key, $timestamp) + * @method static array keys($pattern) + * @method static bool|array scan($it) + * @method static void migrate($host, $port, $keys, $dbIndex, $timeout, $copy = false, $replace = false) + * @method static bool select($dbIndex) + * @method static bool move($key, $dbIndex) + * @method static string|int|bool object($information, $key) + * @method static bool persist($key) + * @method static string randomKey() + * @method static bool rename($srcKey, $dstKey) + * @method static bool renameNx($srcKey, $dstKey) + * @method static string type($key) + * @method static int|array sort($key, $options = []) + * @method static int ttl($key) + * @method static int pttl($key) + * @method static void restore($key, $ttl, $value) + * Hashes methods + * @method static false|int hSet($key, $hashKey, $value) + * @method static bool hSetNx($key, $hashKey, $value) + * @method static false|string hGet($key, $hashKey) + * @method static false|int hLen($key) + * @method static false|int hDel($key, ...$hashKeys) + * @method static array hKeys($key) + * @method static array hVals($key) + * @method static array hGetAll($key) + * @method static bool hExists($key, $hashKey) + * @method static int hIncrBy($key, $hashKey, $value) + * @method static float hIncrByFloat($key, $hashKey, $value) + * @method static bool hMSet($key, $members) + * @method static array hMGet($key, $memberKeys) + * @method static array hScan($key, $iterator, $pattern = '', $count = 0) + * @method static int hStrLen($key, $hashKey) + * Lists methods + * @method static array blPop($keys, $timeout) + * @method static array brPop($keys, $timeout) + * @method static false|string bRPopLPush($srcKey, $dstKey, $timeout) + * @method static false|string lIndex($key, $index) + * @method static int lInsert($key, $position, $pivot, $value) + * @method static false|string lPop($key) + * @method static false|int lPush($key, ...$entries) + * @method static false|int lPushx($key, $value) + * @method static array lRange($key, $start, $end) + * @method static false|int lRem($key, $count, $value) + * @method static bool lSet($key, $index, $value) + * @method static false|array lTrim($key, $start, $end) + * @method static false|string rPop($key) + * @method static false|string rPopLPush($srcKey, $dstKey) + * @method static false|int rPush($key, ...$entries) + * @method static false|int rPushX($key, $value) + * @method static false|int lLen($key) + * Sets methods + * @method static int sAdd($key, $value) + * @method static int sCard($key) + * @method static array sDiff($keys) + * @method static false|int sDiffStore($dst, $keys) + * @method static false|array sInter($keys) + * @method static false|int sInterStore($dst, $keys) + * @method static bool sIsMember($key, $member) + * @method static array sMembers($key) + * @method static bool sMove($src, $dst, $member) + * @method static false|string|array sPop($key, $count = 0) + * @method static false|string|array sRandMember($key, $count = 0) + * @method static int sRem($key, ...$members) + * @method static array sUnion(...$keys) + * @method static false|int sUnionStore($dst, ...$keys) + * @method static false|array sScan($key, $iterator, $pattern = '', $count = 0) + * Sorted sets methods + * @method static array bzPopMin($keys, $timeout) + * @method static array bzPopMax($keys, $timeout) + * @method static int zAdd($key, $score, $value) + * @method static int zCard($key) + * @method static int zCount($key, $start, $end) + * @method static double zIncrBy($key, $value, $member) + * @method static int zinterstore($keyOutput, $arrayZSetKeys, $arrayWeights = [], $aggregateFunction = '') + * @method static array zPopMin($key, $count) + * @method static array zPopMax($key, $count) + * @method static array zRange($key, $start, $end, $withScores = false) + * @method static array zRangeByScore($key, $start, $end, $options = []) + * @method static array zRevRangeByScore($key, $start, $end, $options = []) + * @method static array zRangeByLex($key, $min, $max, $offset = 0, $limit = 0) + * @method static int zRank($key, $member) + * @method static int zRevRank($key, $member) + * @method static int zRem($key, ...$members) + * @method static int zRemRangeByRank($key, $start, $end) + * @method static int zRemRangeByScore($key, $start, $end) + * @method static array zRevRange($key, $start, $end, $withScores = false) + * @method static double zScore($key, $member) + * @method static int zunionstore($keyOutput, $arrayZSetKeys, $arrayWeights = [], $aggregateFunction = '') + * @method static false|array zScan($key, $iterator, $pattern = '', $count = 0) + * HyperLogLogs methods + * @method static int pfAdd($key, $values) + * @method static int pfCount($keys) + * @method static bool pfMerge($dstKey, $srcKeys) + * Geocoding methods + * @method static int geoAdd($key, $longitude, $latitude, $member, ...$items) + * @method static array geoHash($key, ...$members) + * @method static array geoPos($key, ...$members) + * @method static double geoDist($key, $members, $unit = '') + * @method static int|array geoRadius($key, $longitude, $latitude, $radius, $unit, $options = []) + * @method static array geoRadiusByMember($key, $member, $radius, $units, $options = []) + * Streams methods + * @method static int xAck($stream, $group, $arrMessages) + * @method static string xAdd($strKey, $strId, $arrMessage, $iMaxLen = 0, $booApproximate = false) + * @method static array xClaim($strKey, $strGroup, $strConsumer, $minIdleTime, $arrIds, $arrOptions = []) + * @method static int xDel($strKey, $arrIds) + * @method static mixed xGroup($command, $strKey, $strGroup, $strMsgId, $booMKStream = null) + * @method static mixed xInfo($command, $strStream, $strGroup = null) + * @method static int xLen($stream) + * @method static array xPending($strStream, $strGroup, $strStart = 0, $strEnd = 0, $iCount = 0, $strConsumer = null) + * @method static array xRange($strStream, $strStart, $strEnd, $iCount = 0) + * @method static array xRead($arrStreams, $iCount = 0, $iBlock = null) + * @method static array xReadGroup($strGroup, $strConsumer, $arrStreams, $iCount = 0, $iBlock = null) + * @method static array xRevRange($strStream, $strEnd, $strStart, $iCount = 0) + * @method static int xTrim($strStream, $iMaxLen, $booApproximate = null) + * Pub/sub methods + * @method static mixed pSubscribe($patterns, $callback) + * @method static mixed publish($channel, $message) + * @method static mixed subscribe($channels, $callback) + * @method static mixed pubSub($keyword, $argument = null) + * Generic methods + * @method static mixed rawCommand(...$commandAndArgs) + * Transactions methods + * @method static \Redis multi() + * @method static mixed exec() + * @method static mixed discard() + * @method static mixed watch($keys) + * @method static mixed unwatch($keys) + * Scripting methods + * @method static mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null) + * @method static mixed evalSha($scriptSha, $numkeys, ...$arguments) + * @method static mixed script($command, ...$scripts) + * @method static mixed client(...$args) + * @method static null|string getLastError() + * @method static bool clearLastError() + * @method static mixed _prefix($value) + * @method static mixed _serialize($value) + * @method static mixed _unserialize($value) + * Introspection methods + * @method static bool isConnected() + * @method static mixed getHost() + * @method static mixed getPort() + * @method static false|int getDbNum() + * @method static false|double getTimeout() + * @method static mixed getReadTimeout() + * @method static mixed getPersistentID() + * @method static mixed getAuth() + */ +class Redis +{ + + /** + * @var RedisManager + */ + protected static $instance = null; + + /** + * need to install phpredis extension + */ + const PHPREDIS_CLIENT = 'phpredis'; + + /** + * need to install the 'predis/predis' packgage. + * cmd: composer install predis/predis + */ + const PREDIS_CLIENT = 'predis'; + + /** + * Support client collection + */ + static $allowClient = [ + self::PHPREDIS_CLIENT, + self::PREDIS_CLIENT + ]; + + /** + * @return RedisManager + */ + public static function instance(): ?RedisManager + { + if (!static::$instance) { + $config = config('redis'); + $client = $config['client'] ?? self::PHPREDIS_CLIENT; + + if (!in_array($client, static::$allowClient)) { + $client = self::PHPREDIS_CLIENT; + } + + static::$instance = new RedisManager('', $client, $config); + } + return static::$instance; + } + + /** + * Connection. + * @param string $name + * @return Connection + */ + public static function connection(string $name = 'default'): Connection + { + static $timers = []; + $connection = static::instance()->connection($name); + if (!isset($timers[$name])) { + $timers[$name] = Worker::getAllWorkers() ? Timer::add(55, function () use ($connection) { + $connection->get('ping'); + }) : 1; + if (class_exists(Dispatcher::class)) { + $connection->setEventDispatcher(new Dispatcher()); + } + } + return $connection; + } + + /** + * @param string $name + * @param array $arguments + * @return mixed + */ + public static function __callStatic(string $name, array $arguments) + { + return static::connection()->{$name}(... $arguments); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/Request.php b/cacme/vendor/workerman/webman-framework/src/support/Request.php new file mode 100644 index 0000000..e3f6ac3 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Request.php @@ -0,0 +1,24 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +/** + * Class Request + * @package support + */ +class Request extends \Webman\Http\Request +{ + +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/support/Response.php b/cacme/vendor/workerman/webman-framework/src/support/Response.php new file mode 100644 index 0000000..9bc4e1e --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Response.php @@ -0,0 +1,24 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +/** + * Class Response + * @package support + */ +class Response extends \Webman\Http\Response +{ + +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/support/Translation.php b/cacme/vendor/workerman/webman-framework/src/support/Translation.php new file mode 100644 index 0000000..020be83 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/Translation.php @@ -0,0 +1,104 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RegexIterator; +use Symfony\Component\Translation\Translator; +use Webman\Exception\NotFoundException; +use function basename; +use function config; +use function get_realpath; +use function pathinfo; +use function request; +use function substr; + +/** + * Class Translation + * @package support + * @method static string trans(?string $id, array $parameters = [], string $domain = null, string $locale = null) + * @method static void setLocale(string $locale) + * @method static string getLocale() + */ +class Translation +{ + + /** + * @var Translator[] + */ + protected static $instance = []; + + /** + * Instance. + * @param string $plugin + * @return Translator + * @throws NotFoundException + */ + public static function instance(string $plugin = ''): Translator + { + if (!isset(static::$instance[$plugin])) { + $config = config($plugin ? "plugin.$plugin.translation" : 'translation', []); + // Phar support. Compatible with the 'realpath' function in the phar file. + if (!$translationsPath = get_realpath($config['path'])) { + throw new NotFoundException("File {$config['path']} not found"); + } + + static::$instance[$plugin] = $translator = new Translator($config['locale']); + $translator->setFallbackLocales($config['fallback_locale']); + + $classes = [ + 'Symfony\Component\Translation\Loader\PhpFileLoader' => [ + 'extension' => '.php', + 'format' => 'phpfile' + ], + 'Symfony\Component\Translation\Loader\PoFileLoader' => [ + 'extension' => '.po', + 'format' => 'pofile' + ] + ]; + + foreach ($classes as $class => $opts) { + $translator->addLoader($opts['format'], new $class); + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($translationsPath, FilesystemIterator::SKIP_DOTS)); + $files = new RegexIterator($iterator, '/^.+' . preg_quote($opts['extension']) . '$/i', RegexIterator::GET_MATCH); + foreach ($files as $file) { + $file = $file[0]; + $domain = basename($file, $opts['extension']); + $dirName = pathinfo($file, PATHINFO_DIRNAME); + $locale = substr(strrchr($dirName, DIRECTORY_SEPARATOR), 1); + if ($domain && $locale) { + $translator->addResource($opts['format'], $file, $locale, $domain); + } + } + } + } + return static::$instance[$plugin]; + } + + /** + * @param string $name + * @param array $arguments + * @return mixed + * @throws NotFoundException + */ + public static function __callStatic(string $name, array $arguments) + { + $request = request(); + $plugin = $request->plugin ?? ''; + return static::instance($plugin)->{$name}(... $arguments); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/View.php b/cacme/vendor/workerman/webman-framework/src/support/View.php new file mode 100644 index 0000000..f98afe0 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/View.php @@ -0,0 +1,35 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +use function config; +use function request; + +class View +{ + /** + * Assign. + * @param mixed $name + * @param mixed $value + * @return void + */ + public static function assign($name, $value = null) + { + $request = request(); + $plugin = $request->plugin ?? ''; + $handler = config($plugin ? "plugin.$plugin.view.handler" : 'view.handler'); + $handler::assign($name, $value); + } +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/support/bootstrap/LaravelDb.php b/cacme/vendor/workerman/webman-framework/src/support/bootstrap/LaravelDb.php new file mode 100644 index 0000000..2f4b2dd --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/bootstrap/LaravelDb.php @@ -0,0 +1,123 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\bootstrap; + +use Illuminate\Container\Container as IlluminateContainer; +use Illuminate\Database\Capsule\Manager as Capsule; +use Illuminate\Database\MySqlConnection; +use Illuminate\Events\Dispatcher; +use Illuminate\Pagination\Paginator; +use Illuminate\Pagination\CursorPaginator; +use Illuminate\Pagination\Cursor; +use Jenssegers\Mongodb\Connection as JenssegersMongodbConnection; +use MongoDB\Laravel\Connection as LaravelMongodbConnection; +use support\Container; +use Throwable; +use Webman\Bootstrap; +use Workerman\Timer; +use Workerman\Worker; +use function class_exists; +use function config; + +/** + * Class Laravel + * @package support\Bootstrap + */ +class LaravelDb implements Bootstrap +{ + /** + * @param Worker|null $worker + * + * @return void + */ + public static function start(?Worker $worker) + { + if (!class_exists(Capsule::class)) { + return; + } + + $config = config('database', []); + $connections = $config['connections'] ?? []; + if (!$connections) { + return; + } + + $capsule = new Capsule(IlluminateContainer::getInstance()); + + $capsule->getDatabaseManager()->extend('mongodb', function ($config, $name) { + $config['name'] = $name; + return class_exists(LaravelMongodbConnection::class) ? new LaravelMongodbConnection($config) : new JenssegersMongodbConnection($config); + }); + + $default = $config['default'] ?? false; + if ($default) { + $defaultConfig = $connections[$config['default']]; + $capsule->addConnection($defaultConfig); + } + + foreach ($connections as $name => $config) { + $capsule->addConnection($config, $name); + } + + if (class_exists(Dispatcher::class) && !$capsule->getEventDispatcher()) { + $capsule->setEventDispatcher(Container::make(Dispatcher::class, [IlluminateContainer::getInstance()])); + } + + $capsule->setAsGlobal(); + + $capsule->bootEloquent(); + + // Heartbeat + if ($worker) { + Timer::add(55, function () use ($default, $connections, $capsule) { + foreach ($capsule->getDatabaseManager()->getConnections() as $connection) { + /* @var MySqlConnection $connection **/ + if ($connection->getConfig('driver') == 'mysql') { + try { + $connection->select('select 1'); + } catch (Throwable $e) {} + } + } + }); + } + + // Paginator + if (class_exists(Paginator::class)) { + if (method_exists(Paginator::class, 'queryStringResolver')) { + Paginator::queryStringResolver(function () { + $request = request(); + return $request ? $request->queryString() : null; + }); + } + Paginator::currentPathResolver(function () { + $request = request(); + return $request ? $request->path(): '/'; + }); + Paginator::currentPageResolver(function ($pageName = 'page') { + $request = request(); + if (!$request) { + return 1; + } + $page = (int)($request->input($pageName, 1)); + return $page > 0 ? $page : 1; + }); + if (class_exists(CursorPaginator::class)) { + CursorPaginator::currentCursorResolver(function ($cursorName = 'cursor') { + return Cursor::fromEncoded(request()->input($cursorName)); + }); + } + } + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/bootstrap/Session.php b/cacme/vendor/workerman/webman-framework/src/support/bootstrap/Session.php new file mode 100644 index 0000000..7360d0e --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/bootstrap/Session.php @@ -0,0 +1,61 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\bootstrap; + +use Webman\Bootstrap; +use Workerman\Protocols\Http; +use Workerman\Protocols\Http\Session as SessionBase; +use Workerman\Worker; +use function config; +use function property_exists; + +/** + * Class Session + * @package support + */ +class Session implements Bootstrap +{ + + /** + * @param Worker|null $worker + * @return void + */ + public static function start(?Worker $worker) + { + $config = config('session'); + if (property_exists(SessionBase::class, 'name')) { + SessionBase::$name = $config['session_name']; + } else { + Http::sessionName($config['session_name']); + } + SessionBase::handlerClass($config['handler'], $config['config'][$config['type']]); + $map = [ + 'auto_update_timestamp' => 'autoUpdateTimestamp', + 'cookie_lifetime' => 'cookieLifetime', + 'gc_probability' => 'gcProbability', + 'cookie_path' => 'cookiePath', + 'http_only' => 'httpOnly', + 'same_site' => 'sameSite', + 'lifetime' => 'lifetime', + 'domain' => 'domain', + 'secure' => 'secure', + ]; + foreach ($map as $key => $name) { + if (isset($config[$key]) && property_exists(SessionBase::class, $name)) { + SessionBase::${$name} = $config[$key]; + } + } + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/exception/BusinessException.php b/cacme/vendor/workerman/webman-framework/src/support/exception/BusinessException.php new file mode 100644 index 0000000..aee7877 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/exception/BusinessException.php @@ -0,0 +1,38 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\exception; + +use Exception; +use Webman\Http\Request; +use Webman\Http\Response; +use function json_encode; + +/** + * Class BusinessException + * @package support\exception + */ +class BusinessException extends Exception +{ + public function render(Request $request): ?Response + { + if ($request->expectsJson()) { + $code = $this->getCode(); + $json = ['code' => $code ?: 500, 'msg' => $this->getMessage()]; + return new Response(200, ['Content-Type' => 'application/json'], + json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + } + return new Response(200, [], $this->getMessage()); + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/exception/Handler.php b/cacme/vendor/workerman/webman-framework/src/support/exception/Handler.php new file mode 100644 index 0000000..98dc618 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/exception/Handler.php @@ -0,0 +1,47 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\exception; + +use Throwable; +use Webman\Exception\ExceptionHandler; +use Webman\Http\Request; +use Webman\Http\Response; + +/** + * Class Handler + * @package support\exception + */ +class Handler extends ExceptionHandler +{ + public $dontReport = [ + BusinessException::class, + ]; + + public function report(Throwable $exception) + { + parent::report($exception); + } + + public function render(Request $request, Throwable $exception): Response + { + if(($exception instanceof BusinessException) && ($response = $exception->render($request))) + { + return $response; + } + + return parent::render($request, $exception); + } + +} \ No newline at end of file diff --git a/cacme/vendor/workerman/webman-framework/src/support/view/Blade.php b/cacme/vendor/workerman/webman-framework/src/support/view/Blade.php new file mode 100644 index 0000000..ca9634f --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/view/Blade.php @@ -0,0 +1,79 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\view; + +use Jenssegers\Blade\Blade as BladeView; +use Webman\View; +use function app_path; +use function array_merge; +use function base_path; +use function config; +use function is_array; +use function request; +use function runtime_path; + +/** + * Class Blade + * composer require jenssegers/blade + * @package support\view + */ +class Blade implements View +{ + /** + * @var array + */ + protected static $vars = []; + + /** + * Assign. + * @param string|array $name + * @param mixed $value + */ + public static function assign($name, $value = null) + { + static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]); + } + + /** + * Render. + * @param string $template + * @param array $vars + * @param string|null $app + * @param string|null $plugin + * @return string + */ + public static function render(string $template, array $vars, string $app = null, string $plugin = null): string + { + static $views = []; + $request = request(); + $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin; + $app = $app === null ? $request->app : $app; + $configPrefix = $plugin ? "plugin.$plugin." : ''; + $baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path(); + $key = "$plugin-$app"; + if (!isset($views[$key])) { + $viewPath = $app === '' ? "$baseViewPath/view" : "$baseViewPath/$app/view"; + $views[$key] = new BladeView($viewPath, runtime_path() . '/views'); + $extension = config("{$configPrefix}view.extension"); + if ($extension) { + $extension($views[$key]); + } + } + $vars = array_merge(static::$vars, $vars); + $content = $views[$key]->render($template, $vars); + static::$vars = []; + return $content; + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/view/Raw.php b/cacme/vendor/workerman/webman-framework/src/support/view/Raw.php new file mode 100644 index 0000000..5a37ffa --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/view/Raw.php @@ -0,0 +1,84 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\view; + +use Throwable; +use Webman\View; +use function app_path; +use function array_merge; +use function base_path; +use function config; +use function extract; +use function is_array; +use function ob_end_clean; +use function ob_get_clean; +use function ob_start; +use function request; + +/** + * Class Raw + * @package support\view + */ +class Raw implements View +{ + /** + * @var array + */ + protected static $vars = []; + + /** + * Assign. + * @param string|array $name + * @param mixed $value + */ + public static function assign($name, $value = null) + { + static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]); + } + + /** + * Render. + * @param string $template + * @param array $vars + * @param string|null $app + * @param string|null $plugin + * @return false|string + */ + public static function render(string $template, array $vars, string $app = null, string $plugin = null): string + { + $request = request(); + $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin; + $configPrefix = $plugin ? "plugin.$plugin." : ''; + $viewSuffix = config("{$configPrefix}view.options.view_suffix", 'html'); + $app = $app === null ? $request->app : $app; + $baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path(); + $__template_path__ = $app === '' ? "$baseViewPath/view/$template.$viewSuffix" : "$baseViewPath/$app/view/$template.$viewSuffix"; + + extract(static::$vars); + extract($vars); + ob_start(); + // Try to include php file. + try { + include $__template_path__; + } catch (Throwable $e) { + static::$vars = []; + ob_end_clean(); + throw $e; + } + static::$vars = []; + return ob_get_clean(); + } + +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/view/ThinkPHP.php b/cacme/vendor/workerman/webman-framework/src/support/view/ThinkPHP.php new file mode 100644 index 0000000..e6e3f2d --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/view/ThinkPHP.php @@ -0,0 +1,81 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\view; + +use think\Template; +use Webman\View; +use function app_path; +use function array_merge; +use function base_path; +use function config; +use function is_array; +use function ob_get_clean; +use function ob_start; +use function request; +use function runtime_path; + +/** + * Class Blade + * @package support\view + */ +class ThinkPHP implements View +{ + /** + * @var array + */ + protected static $vars = []; + + /** + * Assign. + * @param string|array $name + * @param mixed $value + */ + public static function assign($name, $value = null) + { + static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]); + } + + /** + * Render. + * @param string $template + * @param array $vars + * @param string|null $app + * @param string|null $plugin + * @return false|string + */ + public static function render(string $template, array $vars, string $app = null, string $plugin = null): string + { + $request = request(); + $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin; + $app = $app === null ? $request->app : $app; + $configPrefix = $plugin ? "plugin.$plugin." : ''; + $viewSuffix = config("{$configPrefix}view.options.view_suffix", 'html'); + $baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path(); + $viewPath = $app === '' ? "$baseViewPath/view/" : "$baseViewPath/$app/view/"; + $defaultOptions = [ + 'view_path' => $viewPath, + 'cache_path' => runtime_path() . '/views/', + 'view_suffix' => $viewSuffix + ]; + $options = array_merge($defaultOptions, config("{$configPrefix}view.options", [])); + $views = new Template($options); + ob_start(); + $vars = array_merge(static::$vars, $vars); + $views->fetch($template, $vars); + $content = ob_get_clean(); + static::$vars = []; + return $content; + } +} diff --git a/cacme/vendor/workerman/webman-framework/src/support/view/Twig.php b/cacme/vendor/workerman/webman-framework/src/support/view/Twig.php new file mode 100644 index 0000000..83fc922 --- /dev/null +++ b/cacme/vendor/workerman/webman-framework/src/support/view/Twig.php @@ -0,0 +1,82 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support\view; + +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; +use Twig\Loader\FilesystemLoader; +use Webman\View; +use function app_path; +use function array_merge; +use function base_path; +use function config; +use function is_array; +use function request; + +/** + * Class Blade + * @package support\view + */ +class Twig implements View +{ + /** + * @var array + */ + protected static $vars = []; + + /** + * Assign. + * @param string|array $name + * @param mixed $value + */ + public static function assign($name, $value = null) + { + static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]); + } + + /** + * Render. + * @param string $template + * @param array $vars + * @param string|null $app + * @param string|null $plugin + * @return string + */ + public static function render(string $template, array $vars, string $app = null, string $plugin = null): string + { + static $views = []; + $request = request(); + $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin; + $app = $app === null ? $request->app : $app; + $configPrefix = $plugin ? "plugin.$plugin." : ''; + $viewSuffix = config("{$configPrefix}view.options.view_suffix", 'html'); + $key = "$plugin-$app"; + if (!isset($views[$key])) { + $baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path(); + $viewPath = $app === '' ? "$baseViewPath/view/" : "$baseViewPath/$app/view/"; + $views[$key] = new Environment(new FilesystemLoader($viewPath), config("{$configPrefix}view.options", [])); + $extension = config("{$configPrefix}view.extension"); + if ($extension) { + $extension($views[$key]); + } + } + $vars = array_merge(static::$vars, $vars); + $content = $views[$key]->render("$template.$viewSuffix", $vars); + static::$vars = []; + return $content; + } +} diff --git a/cacme/vendor/workerman/workerman/.github/FUNDING.yml b/cacme/vendor/workerman/workerman/.github/FUNDING.yml new file mode 100644 index 0000000..beae44f --- /dev/null +++ b/cacme/vendor/workerman/workerman/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +open_collective: workerman +patreon: walkor diff --git a/cacme/vendor/workerman/workerman/.gitignore b/cacme/vendor/workerman/workerman/.gitignore new file mode 100644 index 0000000..f3f9e18 --- /dev/null +++ b/cacme/vendor/workerman/workerman/.gitignore @@ -0,0 +1,6 @@ +logs +.buildpath +.project +.settings +.idea +.DS_Store diff --git a/cacme/vendor/workerman/workerman/Autoloader.php b/cacme/vendor/workerman/workerman/Autoloader.php new file mode 100644 index 0000000..7d760e9 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Autoloader.php @@ -0,0 +1,69 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman; + +/** + * Autoload. + */ +class Autoloader +{ + /** + * Autoload root path. + * + * @var string + */ + protected static $_autoloadRootPath = ''; + + /** + * Set autoload root path. + * + * @param string $root_path + * @return void + */ + public static function setRootPath($root_path) + { + self::$_autoloadRootPath = $root_path; + } + + /** + * Load files by namespace. + * + * @param string $name + * @return boolean + */ + public static function loadByNamespace($name) + { + $class_path = \str_replace('\\', \DIRECTORY_SEPARATOR, $name); + if (\strpos($name, 'Workerman\\') === 0) { + $class_file = __DIR__ . \substr($class_path, \strlen('Workerman')) . '.php'; + } else { + if (self::$_autoloadRootPath) { + $class_file = self::$_autoloadRootPath . \DIRECTORY_SEPARATOR . $class_path . '.php'; + } + if (empty($class_file) || !\is_file($class_file)) { + $class_file = __DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . "$class_path.php"; + } + } + + if (\is_file($class_file)) { + require_once($class_file); + if (\class_exists($name, false)) { + return true; + } + } + return false; + } +} + +\spl_autoload_register('\Workerman\Autoloader::loadByNamespace'); \ No newline at end of file diff --git a/cacme/vendor/workerman/workerman/Connection/AsyncTcpConnection.php b/cacme/vendor/workerman/workerman/Connection/AsyncTcpConnection.php new file mode 100644 index 0000000..5bc8676 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Connection/AsyncTcpConnection.php @@ -0,0 +1,378 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Connection; + +use StdClass; +use Workerman\Events\EventInterface; +use Workerman\Lib\Timer; +use Workerman\Worker; +use Exception; + +/** + * AsyncTcpConnection. + */ +class AsyncTcpConnection extends TcpConnection +{ + /** + * Emitted when socket connection is successfully established. + * + * @var callable|null + */ + public $onConnect = null; + + /** + * Transport layer protocol. + * + * @var string + */ + public $transport = 'tcp'; + + /** + * Status. + * + * @var int + */ + protected $_status = self::STATUS_INITIAL; + + /** + * Remote host. + * + * @var string + */ + protected $_remoteHost = ''; + + /** + * Remote port. + * + * @var int + */ + protected $_remotePort = 80; + + /** + * Connect start time. + * + * @var float + */ + protected $_connectStartTime = 0; + + /** + * Remote URI. + * + * @var string + */ + protected $_remoteURI = ''; + + /** + * Context option. + * + * @var array + */ + protected $_contextOption = null; + + /** + * Reconnect timer. + * + * @var int + */ + protected $_reconnectTimer = null; + + + /** + * PHP built-in protocols. + * + * @var array + */ + protected static $_builtinTransports = array( + 'tcp' => 'tcp', + 'udp' => 'udp', + 'unix' => 'unix', + 'ssl' => 'ssl', + 'sslv2' => 'sslv2', + 'sslv3' => 'sslv3', + 'tls' => 'tls' + ); + + /** + * Construct. + * + * @param string $remote_address + * @param array $context_option + * @throws Exception + */ + public function __construct($remote_address, array $context_option = array()) + { + $address_info = \parse_url($remote_address); + if (!$address_info) { + list($scheme, $this->_remoteAddress) = \explode(':', $remote_address, 2); + if('unix' === strtolower($scheme)) { + $this->_remoteAddress = substr($remote_address, strpos($remote_address, '/') + 2); + } + if (!$this->_remoteAddress) { + Worker::safeEcho(new \Exception('bad remote_address')); + } + } else { + if (!isset($address_info['port'])) { + $address_info['port'] = 0; + } + if (!isset($address_info['path'])) { + $address_info['path'] = '/'; + } + if (!isset($address_info['query'])) { + $address_info['query'] = ''; + } else { + $address_info['query'] = '?' . $address_info['query']; + } + $this->_remoteHost = $address_info['host']; + $this->_remotePort = $address_info['port']; + $this->_remoteURI = "{$address_info['path']}{$address_info['query']}"; + $scheme = isset($address_info['scheme']) ? $address_info['scheme'] : 'tcp'; + $this->_remoteAddress = 'unix' === strtolower($scheme) + ? substr($remote_address, strpos($remote_address, '/') + 2) + : $this->_remoteHost . ':' . $this->_remotePort; + } + + $this->id = $this->_id = self::$_idRecorder++; + if(\PHP_INT_MAX === self::$_idRecorder){ + self::$_idRecorder = 0; + } + // Check application layer protocol class. + if (!isset(self::$_builtinTransports[$scheme])) { + $scheme = \ucfirst($scheme); + $this->protocol = '\\Protocols\\' . $scheme; + if (!\class_exists($this->protocol)) { + $this->protocol = "\\Workerman\\Protocols\\$scheme"; + if (!\class_exists($this->protocol)) { + throw new Exception("class \\Protocols\\$scheme not exist"); + } + } + } else { + $this->transport = self::$_builtinTransports[$scheme]; + } + + // For statistics. + ++self::$statistics['connection_count']; + $this->maxSendBufferSize = self::$defaultMaxSendBufferSize; + $this->maxPackageSize = self::$defaultMaxPackageSize; + $this->_contextOption = $context_option; + $this->context = new StdClass; + static::$connections[$this->_id] = $this; + } + + /** + * Do connect. + * + * @return void + */ + public function connect() + { + if ($this->_status !== self::STATUS_INITIAL && $this->_status !== self::STATUS_CLOSING && + $this->_status !== self::STATUS_CLOSED) { + return; + } + $this->_status = self::STATUS_CONNECTING; + $this->_connectStartTime = \microtime(true); + if ($this->transport !== 'unix') { + if (!$this->_remotePort) { + $this->_remotePort = $this->transport === 'ssl' ? 443 : 80; + $this->_remoteAddress = $this->_remoteHost.':'.$this->_remotePort; + } + // Open socket connection asynchronously. + if ($this->_contextOption) { + $context = \stream_context_create($this->_contextOption); + $this->_socket = \stream_socket_client("tcp://{$this->_remoteHost}:{$this->_remotePort}", + $errno, $errstr, 0, \STREAM_CLIENT_ASYNC_CONNECT, $context); + } else { + $this->_socket = \stream_socket_client("tcp://{$this->_remoteHost}:{$this->_remotePort}", + $errno, $errstr, 0, \STREAM_CLIENT_ASYNC_CONNECT); + } + } else { + $this->_socket = \stream_socket_client("{$this->transport}://{$this->_remoteAddress}", $errno, $errstr, 0, + \STREAM_CLIENT_ASYNC_CONNECT); + } + // If failed attempt to emit onError callback. + if (!$this->_socket || !\is_resource($this->_socket)) { + $this->emitError(\WORKERMAN_CONNECT_FAIL, $errstr); + if ($this->_status === self::STATUS_CLOSING) { + $this->destroy(); + } + if ($this->_status === self::STATUS_CLOSED) { + $this->onConnect = null; + } + return; + } + // Add socket to global event loop waiting connection is successfully established or faild. + Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'checkConnection')); + // For windows. + if(\DIRECTORY_SEPARATOR === '\\') { + Worker::$globalEvent->add($this->_socket, EventInterface::EV_EXCEPT, array($this, 'checkConnection')); + } + } + + /** + * Reconnect. + * + * @param int $after + * @return void + */ + public function reconnect($after = 0) + { + $this->_status = self::STATUS_INITIAL; + static::$connections[$this->_id] = $this; + if ($this->_reconnectTimer) { + Timer::del($this->_reconnectTimer); + } + if ($after > 0) { + $this->_reconnectTimer = Timer::add($after, array($this, 'connect'), null, false); + return; + } + $this->connect(); + } + + /** + * CancelReconnect. + */ + public function cancelReconnect() + { + if ($this->_reconnectTimer) { + Timer::del($this->_reconnectTimer); + } + } + + /** + * Get remote address. + * + * @return string + */ + public function getRemoteHost() + { + return $this->_remoteHost; + } + + /** + * Get remote URI. + * + * @return string + */ + public function getRemoteURI() + { + return $this->_remoteURI; + } + + /** + * Try to emit onError callback. + * + * @param int $code + * @param string $msg + * @return void + */ + protected function emitError($code, $msg) + { + $this->_status = self::STATUS_CLOSING; + if ($this->onError) { + try { + \call_user_func($this->onError, $this, $code, $msg); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + } + + /** + * Check connection is successfully established or faild. + * + * @param resource $socket + * @return void + */ + public function checkConnection() + { + // Remove EV_EXPECT for windows. + if(\DIRECTORY_SEPARATOR === '\\') { + Worker::$globalEvent->del($this->_socket, EventInterface::EV_EXCEPT); + } + + // Remove write listener. + Worker::$globalEvent->del($this->_socket, EventInterface::EV_WRITE); + + if ($this->_status !== self::STATUS_CONNECTING) { + return; + } + + // Check socket state. + if ($address = \stream_socket_get_name($this->_socket, true)) { + // Nonblocking. + \stream_set_blocking($this->_socket, false); + // Compatible with hhvm + if (\function_exists('stream_set_read_buffer')) { + \stream_set_read_buffer($this->_socket, 0); + } + // Try to open keepalive for tcp and disable Nagle algorithm. + if (\function_exists('socket_import_stream') && $this->transport === 'tcp') { + $raw_socket = \socket_import_stream($this->_socket); + \socket_set_option($raw_socket, \SOL_SOCKET, \SO_KEEPALIVE, 1); + \socket_set_option($raw_socket, \SOL_TCP, \TCP_NODELAY, 1); + } + + // SSL handshake. + if ($this->transport === 'ssl') { + $this->_sslHandshakeCompleted = $this->doSslHandshake($this->_socket); + if ($this->_sslHandshakeCompleted === false) { + return; + } + } else { + // There are some data waiting to send. + if ($this->_sendBuffer) { + Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); + } + } + + // Register a listener waiting read event. + Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead')); + + $this->_status = self::STATUS_ESTABLISHED; + $this->_remoteAddress = $address; + + // Try to emit onConnect callback. + if ($this->onConnect) { + try { + \call_user_func($this->onConnect, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + // Try to emit protocol::onConnect + if ($this->protocol && \method_exists($this->protocol, 'onConnect')) { + try { + \call_user_func(array($this->protocol, 'onConnect'), $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + } else { + // Connection failed. + $this->emitError(\WORKERMAN_CONNECT_FAIL, 'connect ' . $this->_remoteAddress . ' fail after ' . round(\microtime(true) - $this->_connectStartTime, 4) . ' seconds'); + if ($this->_status === self::STATUS_CLOSING) { + $this->destroy(); + } + if ($this->_status === self::STATUS_CLOSED) { + $this->onConnect = null; + } + } + } +} diff --git a/cacme/vendor/workerman/workerman/Connection/AsyncUdpConnection.php b/cacme/vendor/workerman/workerman/Connection/AsyncUdpConnection.php new file mode 100644 index 0000000..745f060 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Connection/AsyncUdpConnection.php @@ -0,0 +1,203 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Connection; + +use Workerman\Events\EventInterface; +use Workerman\Worker; +use \Exception; + +/** + * AsyncUdpConnection. + */ +class AsyncUdpConnection extends UdpConnection +{ + /** + * Emitted when socket connection is successfully established. + * + * @var callable + */ + public $onConnect = null; + + /** + * Emitted when socket connection closed. + * + * @var callable + */ + public $onClose = null; + + /** + * Connected or not. + * + * @var bool + */ + protected $connected = false; + + /** + * Context option. + * + * @var array + */ + protected $_contextOption = null; + + /** + * Construct. + * + * @param string $remote_address + * @throws Exception + */ + public function __construct($remote_address, $context_option = null) + { + // Get the application layer communication protocol and listening address. + list($scheme, $address) = \explode(':', $remote_address, 2); + // Check application layer protocol class. + if ($scheme !== 'udp') { + $scheme = \ucfirst($scheme); + $this->protocol = '\\Protocols\\' . $scheme; + if (!\class_exists($this->protocol)) { + $this->protocol = "\\Workerman\\Protocols\\$scheme"; + if (!\class_exists($this->protocol)) { + throw new Exception("class \\Protocols\\$scheme not exist"); + } + } + } + + $this->_remoteAddress = \substr($address, 2); + $this->_contextOption = $context_option; + } + + /** + * For udp package. + * + * @param resource $socket + * @return bool + */ + public function baseRead($socket) + { + $recv_buffer = \stream_socket_recvfrom($socket, Worker::MAX_UDP_PACKAGE_SIZE, 0, $remote_address); + if (false === $recv_buffer || empty($remote_address)) { + return false; + } + + if ($this->onMessage) { + if ($this->protocol) { + $parser = $this->protocol; + $recv_buffer = $parser::decode($recv_buffer, $this); + } + ++ConnectionInterface::$statistics['total_request']; + try { + \call_user_func($this->onMessage, $this, $recv_buffer); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + return true; + } + + /** + * Sends data on the connection. + * + * @param string $send_buffer + * @param bool $raw + * @return void|boolean + */ + public function send($send_buffer, $raw = false) + { + if (false === $raw && $this->protocol) { + $parser = $this->protocol; + $send_buffer = $parser::encode($send_buffer, $this); + if ($send_buffer === '') { + return; + } + } + if ($this->connected === false) { + $this->connect(); + } + return \strlen($send_buffer) === \stream_socket_sendto($this->_socket, $send_buffer, 0); + } + + + /** + * Close connection. + * + * @param mixed $data + * @param bool $raw + * + * @return bool + */ + public function close($data = null, $raw = false) + { + if ($data !== null) { + $this->send($data, $raw); + } + Worker::$globalEvent->del($this->_socket, EventInterface::EV_READ); + \fclose($this->_socket); + $this->connected = false; + // Try to emit onClose callback. + if ($this->onClose) { + try { + \call_user_func($this->onClose, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + $this->onConnect = $this->onMessage = $this->onClose = null; + return true; + } + + /** + * Connect. + * + * @return void + */ + public function connect() + { + if ($this->connected === true) { + return; + } + if ($this->_contextOption) { + $context = \stream_context_create($this->_contextOption); + $this->_socket = \stream_socket_client("udp://{$this->_remoteAddress}", $errno, $errmsg, + 30, \STREAM_CLIENT_CONNECT, $context); + } else { + $this->_socket = \stream_socket_client("udp://{$this->_remoteAddress}", $errno, $errmsg); + } + + if (!$this->_socket) { + Worker::safeEcho(new \Exception($errmsg)); + return; + } + + \stream_set_blocking($this->_socket, false); + + if ($this->onMessage) { + Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead')); + } + $this->connected = true; + // Try to emit onConnect callback. + if ($this->onConnect) { + try { + \call_user_func($this->onConnect, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + } + +} diff --git a/cacme/vendor/workerman/workerman/Connection/ConnectionInterface.php b/cacme/vendor/workerman/workerman/Connection/ConnectionInterface.php new file mode 100644 index 0000000..5d815d8 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Connection/ConnectionInterface.php @@ -0,0 +1,126 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Connection; + +/** + * ConnectionInterface. + */ +#[\AllowDynamicProperties] +abstract class ConnectionInterface +{ + /** + * Statistics for status command. + * + * @var array + */ + public static $statistics = array( + 'connection_count' => 0, + 'total_request' => 0, + 'throw_exception' => 0, + 'send_fail' => 0, + ); + + /** + * Emitted when data is received. + * + * @var callable + */ + public $onMessage = null; + + /** + * Emitted when the other end of the socket sends a FIN packet. + * + * @var callable + */ + public $onClose = null; + + /** + * Emitted when an error occurs with connection. + * + * @var callable + */ + public $onError = null; + + /** + * Sends data on the connection. + * + * @param mixed $send_buffer + * @return void|boolean + */ + abstract public function send($send_buffer); + + /** + * Get remote IP. + * + * @return string + */ + abstract public function getRemoteIp(); + + /** + * Get remote port. + * + * @return int + */ + abstract public function getRemotePort(); + + /** + * Get remote address. + * + * @return string + */ + abstract public function getRemoteAddress(); + + /** + * Get local IP. + * + * @return string + */ + abstract public function getLocalIp(); + + /** + * Get local port. + * + * @return int + */ + abstract public function getLocalPort(); + + /** + * Get local address. + * + * @return string + */ + abstract public function getLocalAddress(); + + /** + * Is ipv4. + * + * @return bool + */ + abstract public function isIPv4(); + + /** + * Is ipv6. + * + * @return bool + */ + abstract public function isIPv6(); + + /** + * Close connection. + * + * @param string|null $data + * @return void + */ + abstract public function close($data = null); +} diff --git a/cacme/vendor/workerman/workerman/Connection/TcpConnection.php b/cacme/vendor/workerman/workerman/Connection/TcpConnection.php new file mode 100644 index 0000000..740f01d --- /dev/null +++ b/cacme/vendor/workerman/workerman/Connection/TcpConnection.php @@ -0,0 +1,982 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Connection; + +use Workerman\Events\EventInterface; +use Workerman\Worker; +use \Exception; + +/** + * TcpConnection. + */ +class TcpConnection extends ConnectionInterface +{ + /** + * Read buffer size. + * + * @var int + */ + const READ_BUFFER_SIZE = 65535; + + /** + * Status initial. + * + * @var int + */ + const STATUS_INITIAL = 0; + + /** + * Status connecting. + * + * @var int + */ + const STATUS_CONNECTING = 1; + + /** + * Status connection established. + * + * @var int + */ + const STATUS_ESTABLISHED = 2; + + /** + * Status closing. + * + * @var int + */ + const STATUS_CLOSING = 4; + + /** + * Status closed. + * + * @var int + */ + const STATUS_CLOSED = 8; + + /** + * Emitted when data is received. + * + * @var callable + */ + public $onMessage = null; + + /** + * Emitted when the other end of the socket sends a FIN packet. + * + * @var callable + */ + public $onClose = null; + + /** + * Emitted when an error occurs with connection. + * + * @var callable + */ + public $onError = null; + + /** + * Emitted when the send buffer becomes full. + * + * @var callable + */ + public $onBufferFull = null; + + /** + * Emitted when the send buffer becomes empty. + * + * @var callable + */ + public $onBufferDrain = null; + + /** + * Application layer protocol. + * The format is like this Workerman\\Protocols\\Http. + * + * @var \Workerman\Protocols\ProtocolInterface + */ + public $protocol = null; + + /** + * Transport (tcp/udp/unix/ssl). + * + * @var string + */ + public $transport = 'tcp'; + + /** + * Which worker belong to. + * + * @var Worker + */ + public $worker = null; + + /** + * Bytes read. + * + * @var int + */ + public $bytesRead = 0; + + /** + * Bytes written. + * + * @var int + */ + public $bytesWritten = 0; + + /** + * Connection->id. + * + * @var int + */ + public $id = 0; + + /** + * A copy of $worker->id which used to clean up the connection in worker->connections + * + * @var int + */ + protected $_id = 0; + + /** + * Sets the maximum send buffer size for the current connection. + * OnBufferFull callback will be emited When the send buffer is full. + * + * @var int + */ + public $maxSendBufferSize = 1048576; + + /** + * Context. + * + * @var object|null + */ + public $context = null; + + /** + * Default send buffer size. + * + * @var int + */ + public static $defaultMaxSendBufferSize = 1048576; + + /** + * Sets the maximum acceptable packet size for the current connection. + * + * @var int + */ + public $maxPackageSize = 1048576; + + /** + * Default maximum acceptable packet size. + * + * @var int + */ + public static $defaultMaxPackageSize = 10485760; + + /** + * Id recorder. + * + * @var int + */ + protected static $_idRecorder = 1; + + /** + * Socket + * + * @var resource + */ + protected $_socket = null; + + /** + * Send buffer. + * + * @var string + */ + protected $_sendBuffer = ''; + + /** + * Receive buffer. + * + * @var string + */ + protected $_recvBuffer = ''; + + /** + * Current package length. + * + * @var int + */ + protected $_currentPackageLength = 0; + + /** + * Connection status. + * + * @var int + */ + protected $_status = self::STATUS_ESTABLISHED; + + /** + * Remote address. + * + * @var string + */ + protected $_remoteAddress = ''; + + /** + * Is paused. + * + * @var bool + */ + protected $_isPaused = false; + + /** + * SSL handshake completed or not. + * + * @var bool + */ + protected $_sslHandshakeCompleted = false; + + /** + * All connection instances. + * + * @var array + */ + public static $connections = array(); + + /** + * Status to string. + * + * @var array + */ + public static $_statusToString = array( + self::STATUS_INITIAL => 'INITIAL', + self::STATUS_CONNECTING => 'CONNECTING', + self::STATUS_ESTABLISHED => 'ESTABLISHED', + self::STATUS_CLOSING => 'CLOSING', + self::STATUS_CLOSED => 'CLOSED', + ); + + /** + * Construct. + * + * @param resource $socket + * @param string $remote_address + */ + public function __construct($socket, $remote_address = '') + { + ++self::$statistics['connection_count']; + $this->id = $this->_id = self::$_idRecorder++; + if(self::$_idRecorder === \PHP_INT_MAX){ + self::$_idRecorder = 0; + } + $this->_socket = $socket; + \stream_set_blocking($this->_socket, 0); + // Compatible with hhvm + if (\function_exists('stream_set_read_buffer')) { + \stream_set_read_buffer($this->_socket, 0); + } + Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead')); + $this->maxSendBufferSize = self::$defaultMaxSendBufferSize; + $this->maxPackageSize = self::$defaultMaxPackageSize; + $this->_remoteAddress = $remote_address; + static::$connections[$this->id] = $this; + $this->context = new \stdClass; + } + + /** + * Get status. + * + * @param bool $raw_output + * + * @return int|string + */ + public function getStatus($raw_output = true) + { + if ($raw_output) { + return $this->_status; + } + return self::$_statusToString[$this->_status]; + } + + /** + * Sends data on the connection. + * + * @param mixed $send_buffer + * @param bool $raw + * @return bool|null + */ + public function send($send_buffer, $raw = false) + { + if ($this->_status === self::STATUS_CLOSING || $this->_status === self::STATUS_CLOSED) { + return false; + } + + // Try to call protocol::encode($send_buffer) before sending. + if (false === $raw && $this->protocol !== null) { + $parser = $this->protocol; + $send_buffer = $parser::encode($send_buffer, $this); + if ($send_buffer === '') { + return; + } + } + + if ($this->_status !== self::STATUS_ESTABLISHED || + ($this->transport === 'ssl' && $this->_sslHandshakeCompleted !== true) + ) { + if ($this->_sendBuffer && $this->bufferIsFull()) { + ++self::$statistics['send_fail']; + return false; + } + $this->_sendBuffer .= $send_buffer; + $this->checkBufferWillFull(); + return; + } + + // Attempt to send data directly. + if ($this->_sendBuffer === '') { + if ($this->transport === 'ssl') { + Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); + $this->_sendBuffer = $send_buffer; + $this->checkBufferWillFull(); + return; + } + $len = 0; + try { + $len = @\fwrite($this->_socket, $send_buffer); + } catch (\Exception $e) { + Worker::log($e); + } catch (\Error $e) { + Worker::log($e); + } + // send successful. + if ($len === \strlen($send_buffer)) { + $this->bytesWritten += $len; + return true; + } + // Send only part of the data. + if ($len > 0) { + $this->_sendBuffer = \substr($send_buffer, $len); + $this->bytesWritten += $len; + } else { + // Connection closed? + if (!\is_resource($this->_socket) || \feof($this->_socket)) { + ++self::$statistics['send_fail']; + if ($this->onError) { + try { + \call_user_func($this->onError, $this, \WORKERMAN_SEND_FAIL, 'client closed'); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + $this->destroy(); + return false; + } + $this->_sendBuffer = $send_buffer; + } + Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); + // Check if the send buffer will be full. + $this->checkBufferWillFull(); + return; + } + + if ($this->bufferIsFull()) { + ++self::$statistics['send_fail']; + return false; + } + + $this->_sendBuffer .= $send_buffer; + // Check if the send buffer is full. + $this->checkBufferWillFull(); + } + + /** + * Get remote IP. + * + * @return string + */ + public function getRemoteIp() + { + $pos = \strrpos($this->_remoteAddress, ':'); + if ($pos) { + return (string) \substr($this->_remoteAddress, 0, $pos); + } + return ''; + } + + /** + * Get remote port. + * + * @return int + */ + public function getRemotePort() + { + if ($this->_remoteAddress) { + return (int) \substr(\strrchr($this->_remoteAddress, ':'), 1); + } + return 0; + } + + /** + * Get remote address. + * + * @return string + */ + public function getRemoteAddress() + { + return $this->_remoteAddress; + } + + /** + * Get local IP. + * + * @return string + */ + public function getLocalIp() + { + $address = $this->getLocalAddress(); + $pos = \strrpos($address, ':'); + if (!$pos) { + return ''; + } + return \substr($address, 0, $pos); + } + + /** + * Get local port. + * + * @return int + */ + public function getLocalPort() + { + $address = $this->getLocalAddress(); + $pos = \strrpos($address, ':'); + if (!$pos) { + return 0; + } + return (int)\substr(\strrchr($address, ':'), 1); + } + + /** + * Get local address. + * + * @return string + */ + public function getLocalAddress() + { + if (!\is_resource($this->_socket)) { + return ''; + } + return (string)@\stream_socket_get_name($this->_socket, false); + } + + /** + * Get send buffer queue size. + * + * @return integer + */ + public function getSendBufferQueueSize() + { + return \strlen($this->_sendBuffer); + } + + /** + * Get recv buffer queue size. + * + * @return integer + */ + public function getRecvBufferQueueSize() + { + return \strlen($this->_recvBuffer); + } + + /** + * Is ipv4. + * + * return bool. + */ + public function isIpV4() + { + if ($this->transport === 'unix') { + return false; + } + return \strpos($this->getRemoteIp(), ':') === false; + } + + /** + * Is ipv6. + * + * return bool. + */ + public function isIpV6() + { + if ($this->transport === 'unix') { + return false; + } + return \strpos($this->getRemoteIp(), ':') !== false; + } + + /** + * Pauses the reading of data. That is onMessage will not be emitted. Useful to throttle back an upload. + * + * @return void + */ + public function pauseRecv() + { + Worker::$globalEvent->del($this->_socket, EventInterface::EV_READ); + $this->_isPaused = true; + } + + /** + * Resumes reading after a call to pauseRecv. + * + * @return void + */ + public function resumeRecv() + { + if ($this->_isPaused === true) { + Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead')); + $this->_isPaused = false; + $this->baseRead($this->_socket, false); + } + } + + + + /** + * Base read handler. + * + * @param resource $socket + * @param bool $check_eof + * @return void + */ + public function baseRead($socket, $check_eof = true) + { + // SSL handshake. + if ($this->transport === 'ssl' && $this->_sslHandshakeCompleted !== true) { + if ($this->doSslHandshake($socket)) { + $this->_sslHandshakeCompleted = true; + if ($this->_sendBuffer) { + Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); + } + } else { + return; + } + } + + $buffer = ''; + try { + $buffer = @\fread($socket, self::READ_BUFFER_SIZE); + } catch (\Exception $e) {} catch (\Error $e) {} + + // Check connection closed. + if ($buffer === '' || $buffer === false) { + if ($check_eof && (\feof($socket) || !\is_resource($socket) || $buffer === false)) { + $this->destroy(); + return; + } + } else { + $this->bytesRead += \strlen($buffer); + $this->_recvBuffer .= $buffer; + } + + // If the application layer protocol has been set up. + if ($this->protocol !== null) { + $parser = $this->protocol; + while ($this->_recvBuffer !== '' && !$this->_isPaused) { + // The current packet length is known. + if ($this->_currentPackageLength) { + // Data is not enough for a package. + if ($this->_currentPackageLength > \strlen($this->_recvBuffer)) { + break; + } + } else { + // Get current package length. + try { + $this->_currentPackageLength = $parser::input($this->_recvBuffer, $this); + } catch (\Exception $e) {} catch (\Error $e) {} + // The packet length is unknown. + if ($this->_currentPackageLength === 0) { + break; + } elseif ($this->_currentPackageLength > 0 && $this->_currentPackageLength <= $this->maxPackageSize) { + // Data is not enough for a package. + if ($this->_currentPackageLength > \strlen($this->_recvBuffer)) { + break; + } + } // Wrong package. + else { + Worker::safeEcho('Error package. package_length=' . \var_export($this->_currentPackageLength, true)); + $this->destroy(); + return; + } + } + + // The data is enough for a packet. + ++self::$statistics['total_request']; + // The current packet length is equal to the length of the buffer. + if (\strlen($this->_recvBuffer) === $this->_currentPackageLength) { + $one_request_buffer = $this->_recvBuffer; + $this->_recvBuffer = ''; + } else { + // Get a full package from the buffer. + $one_request_buffer = \substr($this->_recvBuffer, 0, $this->_currentPackageLength); + // Remove the current package from the receive buffer. + $this->_recvBuffer = \substr($this->_recvBuffer, $this->_currentPackageLength); + } + // Reset the current packet length to 0. + $this->_currentPackageLength = 0; + if (!$this->onMessage) { + continue; + } + try { + // Decode request buffer before Emitting onMessage callback. + \call_user_func($this->onMessage, $this, $parser::decode($one_request_buffer, $this)); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + return; + } + + if ($this->_recvBuffer === '' || $this->_isPaused) { + return; + } + + // Applications protocol is not set. + ++self::$statistics['total_request']; + if (!$this->onMessage) { + $this->_recvBuffer = ''; + return; + } + try { + \call_user_func($this->onMessage, $this, $this->_recvBuffer); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + // Clean receive buffer. + $this->_recvBuffer = ''; + } + + /** + * Base write handler. + * + * @return void|bool + */ + public function baseWrite() + { + \set_error_handler(function(){}); + if ($this->transport === 'ssl') { + $len = @\fwrite($this->_socket, $this->_sendBuffer, 8192); + } else { + $len = @\fwrite($this->_socket, $this->_sendBuffer); + } + \restore_error_handler(); + if ($len === \strlen($this->_sendBuffer)) { + $this->bytesWritten += $len; + Worker::$globalEvent->del($this->_socket, EventInterface::EV_WRITE); + $this->_sendBuffer = ''; + // Try to emit onBufferDrain callback when the send buffer becomes empty. + if ($this->onBufferDrain) { + try { + \call_user_func($this->onBufferDrain, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + if ($this->_status === self::STATUS_CLOSING) { + $this->destroy(); + } + return true; + } + if ($len > 0) { + $this->bytesWritten += $len; + $this->_sendBuffer = \substr($this->_sendBuffer, $len); + } else { + ++self::$statistics['send_fail']; + $this->destroy(); + } + } + + /** + * SSL handshake. + * + * @param resource $socket + * @return bool + */ + public function doSslHandshake($socket){ + if (\feof($socket)) { + $this->destroy(); + return false; + } + $async = $this instanceof AsyncTcpConnection; + + /** + * We disabled ssl3 because https://blog.qualys.com/ssllabs/2014/10/15/ssl-3-is-dead-killed-by-the-poodle-attack. + * You can enable ssl3 by the codes below. + */ + /*if($async){ + $type = STREAM_CRYPTO_METHOD_SSLv2_CLIENT | STREAM_CRYPTO_METHOD_SSLv23_CLIENT | STREAM_CRYPTO_METHOD_SSLv3_CLIENT; + }else{ + $type = STREAM_CRYPTO_METHOD_SSLv2_SERVER | STREAM_CRYPTO_METHOD_SSLv23_SERVER | STREAM_CRYPTO_METHOD_SSLv3_SERVER; + }*/ + + if($async){ + $type = \STREAM_CRYPTO_METHOD_SSLv2_CLIENT | \STREAM_CRYPTO_METHOD_SSLv23_CLIENT; + }else{ + $type = \STREAM_CRYPTO_METHOD_SSLv2_SERVER | \STREAM_CRYPTO_METHOD_SSLv23_SERVER; + } + + // Hidden error. + \set_error_handler(function($errno, $errstr, $file){ + if (!Worker::$daemonize) { + Worker::safeEcho("SSL handshake error: $errstr \n"); + } + }); + $ret = \stream_socket_enable_crypto($socket, true, $type); + \restore_error_handler(); + // Negotiation has failed. + if (false === $ret) { + $this->destroy(); + return false; + } elseif (0 === $ret) { + // There isn't enough data and should try again. + return 0; + } + if (isset($this->onSslHandshake)) { + try { + \call_user_func($this->onSslHandshake, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + return true; + } + + /** + * This method pulls all the data out of a readable stream, and writes it to the supplied destination. + * + * @param self $dest + * @return void + */ + public function pipe(self $dest) + { + $source = $this; + $this->onMessage = function ($source, $data) use ($dest) { + $dest->send($data); + }; + $this->onClose = function ($source) use ($dest) { + $dest->close(); + }; + $dest->onBufferFull = function ($dest) use ($source) { + $source->pauseRecv(); + }; + $dest->onBufferDrain = function ($dest) use ($source) { + $source->resumeRecv(); + }; + } + + /** + * Remove $length of data from receive buffer. + * + * @param int $length + * @return void + */ + public function consumeRecvBuffer($length) + { + $this->_recvBuffer = \substr($this->_recvBuffer, $length); + } + + /** + * Close connection. + * + * @param mixed $data + * @param bool $raw + * @return void + */ + public function close($data = null, $raw = false) + { + if($this->_status === self::STATUS_CONNECTING){ + $this->destroy(); + return; + } + + if ($this->_status === self::STATUS_CLOSING || $this->_status === self::STATUS_CLOSED) { + return; + } + + if ($data !== null) { + $this->send($data, $raw); + } + + $this->_status = self::STATUS_CLOSING; + + if ($this->_sendBuffer === '') { + $this->destroy(); + } else { + $this->pauseRecv(); + } + } + + /** + * Get the real socket. + * + * @return resource + */ + public function getSocket() + { + return $this->_socket; + } + + /** + * Check whether the send buffer will be full. + * + * @return void + */ + protected function checkBufferWillFull() + { + if ($this->maxSendBufferSize <= \strlen($this->_sendBuffer)) { + if ($this->onBufferFull) { + try { + \call_user_func($this->onBufferFull, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + } + } + + /** + * Whether send buffer is full. + * + * @return bool + */ + protected function bufferIsFull() + { + // Buffer has been marked as full but still has data to send then the packet is discarded. + if ($this->maxSendBufferSize <= \strlen($this->_sendBuffer)) { + if ($this->onError) { + try { + \call_user_func($this->onError, $this, \WORKERMAN_SEND_FAIL, 'send buffer full and drop package'); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + return true; + } + return false; + } + + /** + * Whether send buffer is Empty. + * + * @return bool + */ + public function bufferIsEmpty() + { + return empty($this->_sendBuffer); + } + + /** + * Destroy connection. + * + * @return void + */ + public function destroy() + { + // Avoid repeated calls. + if ($this->_status === self::STATUS_CLOSED) { + return; + } + // Remove event listener. + Worker::$globalEvent->del($this->_socket, EventInterface::EV_READ); + Worker::$globalEvent->del($this->_socket, EventInterface::EV_WRITE); + + // Close socket. + try { + @\fclose($this->_socket); + } catch (\Exception $e) {} catch (\Error $e) {} + + $this->_status = self::STATUS_CLOSED; + // Try to emit onClose callback. + if ($this->onClose) { + try { + \call_user_func($this->onClose, $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + // Try to emit protocol::onClose + if ($this->protocol && \method_exists($this->protocol, 'onClose')) { + try { + \call_user_func(array($this->protocol, 'onClose'), $this); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + $this->_sendBuffer = $this->_recvBuffer = ''; + $this->_currentPackageLength = 0; + $this->_isPaused = $this->_sslHandshakeCompleted = false; + if ($this->_status === self::STATUS_CLOSED) { + // Cleaning up the callback to avoid memory leaks. + $this->onMessage = $this->onClose = $this->onError = $this->onBufferFull = $this->onBufferDrain = null; + // Remove from worker->connections. + if ($this->worker) { + unset($this->worker->connections[$this->_id]); + } + unset(static::$connections[$this->_id]); + } + } + + /** + * Destruct. + * + * @return void + */ + public function __destruct() + { + static $mod; + self::$statistics['connection_count']--; + if (Worker::getGracefulStop()) { + if (!isset($mod)) { + $mod = \ceil((self::$statistics['connection_count'] + 1) / 3); + } + + if (0 === self::$statistics['connection_count'] % $mod) { + Worker::log('worker[' . \posix_getpid() . '] remains ' . self::$statistics['connection_count'] . ' connection(s)'); + } + + if(0 === self::$statistics['connection_count']) { + Worker::stopAll(); + } + } + } +} diff --git a/cacme/vendor/workerman/workerman/Connection/UdpConnection.php b/cacme/vendor/workerman/workerman/Connection/UdpConnection.php new file mode 100644 index 0000000..9cd95ba --- /dev/null +++ b/cacme/vendor/workerman/workerman/Connection/UdpConnection.php @@ -0,0 +1,208 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Connection; + +/** + * UdpConnection. + */ +class UdpConnection extends ConnectionInterface +{ + /** + * Application layer protocol. + * The format is like this Workerman\\Protocols\\Http. + * + * @var \Workerman\Protocols\ProtocolInterface + */ + public $protocol = null; + + /** + * Transport layer protocol. + * + * @var string + */ + public $transport = 'udp'; + + /** + * Udp socket. + * + * @var resource + */ + protected $_socket = null; + + /** + * Remote address. + * + * @var string + */ + protected $_remoteAddress = ''; + + /** + * Construct. + * + * @param resource $socket + * @param string $remote_address + */ + public function __construct($socket, $remote_address) + { + $this->_socket = $socket; + $this->_remoteAddress = $remote_address; + } + + /** + * Sends data on the connection. + * + * @param string $send_buffer + * @param bool $raw + * @return void|boolean + */ + public function send($send_buffer, $raw = false) + { + if (false === $raw && $this->protocol) { + $parser = $this->protocol; + $send_buffer = $parser::encode($send_buffer, $this); + if ($send_buffer === '') { + return; + } + } + return \strlen($send_buffer) === \stream_socket_sendto($this->_socket, $send_buffer, 0, $this->isIpV6() ? '[' . $this->getRemoteIp() . ']:' . $this->getRemotePort() : $this->_remoteAddress); + } + + /** + * Get remote IP. + * + * @return string + */ + public function getRemoteIp() + { + $pos = \strrpos($this->_remoteAddress, ':'); + if ($pos) { + return \trim(\substr($this->_remoteAddress, 0, $pos), '[]'); + } + return ''; + } + + /** + * Get remote port. + * + * @return int + */ + public function getRemotePort() + { + if ($this->_remoteAddress) { + return (int)\substr(\strrchr($this->_remoteAddress, ':'), 1); + } + return 0; + } + + /** + * Get remote address. + * + * @return string + */ + public function getRemoteAddress() + { + return $this->_remoteAddress; + } + + /** + * Get local IP. + * + * @return string + */ + public function getLocalIp() + { + $address = $this->getLocalAddress(); + $pos = \strrpos($address, ':'); + if (!$pos) { + return ''; + } + return \substr($address, 0, $pos); + } + + /** + * Get local port. + * + * @return int + */ + public function getLocalPort() + { + $address = $this->getLocalAddress(); + $pos = \strrpos($address, ':'); + if (!$pos) { + return 0; + } + return (int)\substr(\strrchr($address, ':'), 1); + } + + /** + * Get local address. + * + * @return string + */ + public function getLocalAddress() + { + return (string)@\stream_socket_get_name($this->_socket, false); + } + + /** + * Is ipv4. + * + * @return bool. + */ + public function isIpV4() + { + if ($this->transport === 'unix') { + return false; + } + return \strpos($this->getRemoteIp(), ':') === false; + } + + /** + * Is ipv6. + * + * @return bool. + */ + public function isIpV6() + { + if ($this->transport === 'unix') { + return false; + } + return \strpos($this->getRemoteIp(), ':') !== false; + } + + /** + * Close connection. + * + * @param mixed $data + * @param bool $raw + * @return bool + */ + public function close($data = null, $raw = false) + { + if ($data !== null) { + $this->send($data, $raw); + } + return true; + } + + /** + * Get the real socket. + * + * @return resource + */ + public function getSocket() + { + return $this->_socket; + } +} diff --git a/cacme/vendor/workerman/workerman/Events/Ev.php b/cacme/vendor/workerman/workerman/Events/Ev.php new file mode 100644 index 0000000..8e21bc3 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/Ev.php @@ -0,0 +1,189 @@ + + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +use Workerman\Worker; +use \EvWatcher; + +/** + * ev eventloop + */ +class Ev implements EventInterface +{ + /** + * All listeners for read/write event. + * + * @var array + */ + protected $_allEvents = array(); + + /** + * Event listeners of signal. + * + * @var array + */ + protected $_eventSignal = array(); + + /** + * All timer event listeners. + * [func, args, event, flag, time_interval] + * + * @var array + */ + protected $_eventTimer = array(); + + /** + * Timer id. + * + * @var int + */ + protected static $_timerId = 1; + + /** + * Add a timer. + * {@inheritdoc} + */ + public function add($fd, $flag, $func, $args = null) + { + $callback = function ($event, $socket) use ($fd, $func) { + try { + \call_user_func($func, $fd); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + }; + switch ($flag) { + case self::EV_SIGNAL: + $event = new \EvSignal($fd, $callback); + $this->_eventSignal[$fd] = $event; + return true; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + $repeat = $flag === self::EV_TIMER_ONCE ? 0 : $fd; + $param = array($func, (array)$args, $flag, $fd, self::$_timerId); + $event = new \EvTimer($fd, $repeat, array($this, 'timerCallback'), $param); + $this->_eventTimer[self::$_timerId] = $event; + return self::$_timerId++; + default : + $fd_key = (int)$fd; + $real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE; + $event = new \EvIo($fd, $real_flag, $callback); + $this->_allEvents[$fd_key][$flag] = $event; + return true; + } + + } + + /** + * Remove a timer. + * {@inheritdoc} + */ + public function del($fd, $flag) + { + switch ($flag) { + case self::EV_READ: + case self::EV_WRITE: + $fd_key = (int)$fd; + if (isset($this->_allEvents[$fd_key][$flag])) { + $this->_allEvents[$fd_key][$flag]->stop(); + unset($this->_allEvents[$fd_key][$flag]); + } + if (empty($this->_allEvents[$fd_key])) { + unset($this->_allEvents[$fd_key]); + } + break; + case self::EV_SIGNAL: + $fd_key = (int)$fd; + if (isset($this->_eventSignal[$fd_key])) { + $this->_eventSignal[$fd_key]->stop(); + unset($this->_eventSignal[$fd_key]); + } + break; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + if (isset($this->_eventTimer[$fd])) { + $this->_eventTimer[$fd]->stop(); + unset($this->_eventTimer[$fd]); + } + break; + } + return true; + } + + /** + * Timer callback. + * + * @param EvWatcher $event + */ + public function timerCallback(EvWatcher $event) + { + $param = $event->data; + $timer_id = $param[4]; + if ($param[2] === self::EV_TIMER_ONCE) { + $this->_eventTimer[$timer_id]->stop(); + unset($this->_eventTimer[$timer_id]); + } + try { + \call_user_func_array($param[0], $param[1]); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + + /** + * Remove all timers. + * + * @return void + */ + public function clearAllTimer() + { + foreach ($this->_eventTimer as $event) { + $event->stop(); + } + $this->_eventTimer = array(); + } + + /** + * Main loop. + * + * @see EventInterface::loop() + */ + public function loop() + { + \Ev::run(); + } + + /** + * Destroy loop. + * + * @return void + */ + public function destroy() + { + \Ev::stop(\Ev::BREAK_ALL); + } + + /** + * Get timer count. + * + * @return integer + */ + public function getTimerCount() + { + return \count($this->_eventTimer); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/Event.php b/cacme/vendor/workerman/workerman/Events/Event.php new file mode 100644 index 0000000..9e25521 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/Event.php @@ -0,0 +1,215 @@ + + * @copyright 有个鬼<42765633@qq.com> + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +use Workerman\Worker; + +/** + * libevent eventloop + */ +class Event implements EventInterface +{ + /** + * Event base. + * @var object + */ + protected $_eventBase = null; + + /** + * All listeners for read/write event. + * @var array + */ + protected $_allEvents = array(); + + /** + * Event listeners of signal. + * @var array + */ + protected $_eventSignal = array(); + + /** + * All timer event listeners. + * [func, args, event, flag, time_interval] + * @var array + */ + protected $_eventTimer = array(); + + /** + * Timer id. + * @var int + */ + protected static $_timerId = 1; + + /** + * construct + * @return void + */ + public function __construct() + { + if (\class_exists('\\\\EventBase', false)) { + $class_name = '\\\\EventBase'; + } else { + $class_name = '\EventBase'; + } + $this->_eventBase = new $class_name(); + } + + /** + * @see EventInterface::add() + */ + public function add($fd, $flag, $func, $args=array()) + { + if (\class_exists('\\\\Event', false)) { + $class_name = '\\\\Event'; + } else { + $class_name = '\Event'; + } + switch ($flag) { + case self::EV_SIGNAL: + + $fd_key = (int)$fd; + $event = $class_name::signal($this->_eventBase, $fd, $func); + if (!$event||!$event->add()) { + return false; + } + $this->_eventSignal[$fd_key] = $event; + return true; + + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + + $param = array($func, (array)$args, $flag, $fd, self::$_timerId); + $event = new $class_name($this->_eventBase, -1, $class_name::TIMEOUT|$class_name::PERSIST, array($this, "timerCallback"), $param); + if (!$event||!$event->addTimer($fd)) { + return false; + } + $this->_eventTimer[self::$_timerId] = $event; + return self::$_timerId++; + + default : + $fd_key = (int)$fd; + $real_flag = $flag === self::EV_READ ? $class_name::READ | $class_name::PERSIST : $class_name::WRITE | $class_name::PERSIST; + $event = new $class_name($this->_eventBase, $fd, $real_flag, $func, $fd); + if (!$event||!$event->add()) { + return false; + } + $this->_allEvents[$fd_key][$flag] = $event; + return true; + } + } + + /** + * @see Events\EventInterface::del() + */ + public function del($fd, $flag) + { + switch ($flag) { + + case self::EV_READ: + case self::EV_WRITE: + + $fd_key = (int)$fd; + if (isset($this->_allEvents[$fd_key][$flag])) { + $this->_allEvents[$fd_key][$flag]->del(); + unset($this->_allEvents[$fd_key][$flag]); + } + if (empty($this->_allEvents[$fd_key])) { + unset($this->_allEvents[$fd_key]); + } + break; + + case self::EV_SIGNAL: + $fd_key = (int)$fd; + if (isset($this->_eventSignal[$fd_key])) { + $this->_eventSignal[$fd_key]->del(); + unset($this->_eventSignal[$fd_key]); + } + break; + + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + if (isset($this->_eventTimer[$fd])) { + $this->_eventTimer[$fd]->del(); + unset($this->_eventTimer[$fd]); + } + break; + } + return true; + } + + /** + * Timer callback. + * @param int|null $fd + * @param int $what + * @param int $timer_id + */ + public function timerCallback($fd, $what, $param) + { + $timer_id = $param[4]; + + if ($param[2] === self::EV_TIMER_ONCE) { + $this->_eventTimer[$timer_id]->del(); + unset($this->_eventTimer[$timer_id]); + } + + try { + \call_user_func_array($param[0], $param[1]); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + + /** + * @see Events\EventInterface::clearAllTimer() + * @return void + */ + public function clearAllTimer() + { + foreach ($this->_eventTimer as $event) { + $event->del(); + } + $this->_eventTimer = array(); + } + + + /** + * @see EventInterface::loop() + */ + public function loop() + { + $this->_eventBase->loop(); + } + + /** + * Destroy loop. + * + * @return void + */ + public function destroy() + { + $this->_eventBase->exit(); + } + + /** + * Get timer count. + * + * @return integer + */ + public function getTimerCount() + { + return \count($this->_eventTimer); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/EventInterface.php b/cacme/vendor/workerman/workerman/Events/EventInterface.php new file mode 100644 index 0000000..e6f59c6 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/EventInterface.php @@ -0,0 +1,107 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +interface EventInterface +{ + /** + * Read event. + * + * @var int + */ + const EV_READ = 1; + + /** + * Write event. + * + * @var int + */ + const EV_WRITE = 2; + + /** + * Except event + * + * @var int + */ + const EV_EXCEPT = 3; + + /** + * Signal event. + * + * @var int + */ + const EV_SIGNAL = 4; + + /** + * Timer event. + * + * @var int + */ + const EV_TIMER = 8; + + /** + * Timer once event. + * + * @var int + */ + const EV_TIMER_ONCE = 16; + + /** + * Add event listener to event loop. + * + * @param mixed $fd + * @param int $flag + * @param callable $func + * @param array $args + * @return bool + */ + public function add($fd, $flag, $func, $args = array()); + + /** + * Remove event listener from event loop. + * + * @param mixed $fd + * @param int $flag + * @return bool + */ + public function del($fd, $flag); + + /** + * Remove all timers. + * + * @return void + */ + public function clearAllTimer(); + + /** + * Main loop. + * + * @return void + */ + public function loop(); + + /** + * Destroy loop. + * + * @return mixed + */ + public function destroy(); + + /** + * Get Timer count. + * + * @return mixed + */ + public function getTimerCount(); +} diff --git a/cacme/vendor/workerman/workerman/Events/Libevent.php b/cacme/vendor/workerman/workerman/Events/Libevent.php new file mode 100644 index 0000000..5f61e9c --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/Libevent.php @@ -0,0 +1,225 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +use Workerman\Worker; + +/** + * libevent eventloop + */ +class Libevent implements EventInterface +{ + /** + * Event base. + * + * @var resource + */ + protected $_eventBase = null; + + /** + * All listeners for read/write event. + * + * @var array + */ + protected $_allEvents = array(); + + /** + * Event listeners of signal. + * + * @var array + */ + protected $_eventSignal = array(); + + /** + * All timer event listeners. + * [func, args, event, flag, time_interval] + * + * @var array + */ + protected $_eventTimer = array(); + + /** + * construct + */ + public function __construct() + { + $this->_eventBase = \event_base_new(); + } + + /** + * {@inheritdoc} + */ + public function add($fd, $flag, $func, $args = array()) + { + switch ($flag) { + case self::EV_SIGNAL: + $fd_key = (int)$fd; + $real_flag = \EV_SIGNAL | \EV_PERSIST; + $this->_eventSignal[$fd_key] = \event_new(); + if (!\event_set($this->_eventSignal[$fd_key], $fd, $real_flag, $func, null)) { + return false; + } + if (!\event_base_set($this->_eventSignal[$fd_key], $this->_eventBase)) { + return false; + } + if (!\event_add($this->_eventSignal[$fd_key])) { + return false; + } + return true; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + $event = \event_new(); + $timer_id = (int)$event; + if (!\event_set($event, 0, \EV_TIMEOUT, array($this, 'timerCallback'), $timer_id)) { + return false; + } + + if (!\event_base_set($event, $this->_eventBase)) { + return false; + } + + $time_interval = $fd * 1000000; + if (!\event_add($event, $time_interval)) { + return false; + } + $this->_eventTimer[$timer_id] = array($func, (array)$args, $event, $flag, $time_interval); + return $timer_id; + + default : + $fd_key = (int)$fd; + $real_flag = $flag === self::EV_READ ? \EV_READ | \EV_PERSIST : \EV_WRITE | \EV_PERSIST; + + $event = \event_new(); + + if (!\event_set($event, $fd, $real_flag, $func, null)) { + return false; + } + + if (!\event_base_set($event, $this->_eventBase)) { + return false; + } + + if (!\event_add($event)) { + return false; + } + + $this->_allEvents[$fd_key][$flag] = $event; + + return true; + } + + } + + /** + * {@inheritdoc} + */ + public function del($fd, $flag) + { + switch ($flag) { + case self::EV_READ: + case self::EV_WRITE: + $fd_key = (int)$fd; + if (isset($this->_allEvents[$fd_key][$flag])) { + \event_del($this->_allEvents[$fd_key][$flag]); + unset($this->_allEvents[$fd_key][$flag]); + } + if (empty($this->_allEvents[$fd_key])) { + unset($this->_allEvents[$fd_key]); + } + break; + case self::EV_SIGNAL: + $fd_key = (int)$fd; + if (isset($this->_eventSignal[$fd_key])) { + \event_del($this->_eventSignal[$fd_key]); + unset($this->_eventSignal[$fd_key]); + } + break; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + // 这里 fd 为timerid + if (isset($this->_eventTimer[$fd])) { + \event_del($this->_eventTimer[$fd][2]); + unset($this->_eventTimer[$fd]); + } + break; + } + return true; + } + + /** + * Timer callback. + * + * @param mixed $_null1 + * @param int $_null2 + * @param mixed $timer_id + */ + protected function timerCallback($_null1, $_null2, $timer_id) + { + if ($this->_eventTimer[$timer_id][3] === self::EV_TIMER) { + \event_add($this->_eventTimer[$timer_id][2], $this->_eventTimer[$timer_id][4]); + } + try { + \call_user_func_array($this->_eventTimer[$timer_id][0], $this->_eventTimer[$timer_id][1]); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + if (isset($this->_eventTimer[$timer_id]) && $this->_eventTimer[$timer_id][3] === self::EV_TIMER_ONCE) { + $this->del($timer_id, self::EV_TIMER_ONCE); + } + } + + /** + * {@inheritdoc} + */ + public function clearAllTimer() + { + foreach ($this->_eventTimer as $task_data) { + \event_del($task_data[2]); + } + $this->_eventTimer = array(); + } + + /** + * {@inheritdoc} + */ + public function loop() + { + \event_base_loop($this->_eventBase); + } + + /** + * Destroy loop. + * + * @return void + */ + public function destroy() + { + foreach ($this->_eventSignal as $event) { + \event_del($event); + } + } + + /** + * Get timer count. + * + * @return integer + */ + public function getTimerCount() + { + return \count($this->_eventTimer); + } +} + diff --git a/cacme/vendor/workerman/workerman/Events/React/Base.php b/cacme/vendor/workerman/workerman/Events/React/Base.php new file mode 100644 index 0000000..bce4f73 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/React/Base.php @@ -0,0 +1,264 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events\React; + +use Workerman\Events\EventInterface; +use React\EventLoop\TimerInterface; +use React\EventLoop\LoopInterface; + +/** + * Class StreamSelectLoop + * @package Workerman\Events\React + */ +class Base implements LoopInterface +{ + /** + * @var array + */ + protected $_timerIdMap = array(); + + /** + * @var int + */ + protected $_timerIdIndex = 0; + + /** + * @var array + */ + protected $_signalHandlerMap = array(); + + /** + * @var LoopInterface + */ + protected $_eventLoop = null; + + /** + * Base constructor. + */ + public function __construct() + { + $this->_eventLoop = new \React\EventLoop\StreamSelectLoop(); + } + + /** + * Add event listener to event loop. + * + * @param int $fd + * @param int $flag + * @param callable $func + * @param array $args + * @return bool + */ + public function add($fd, $flag, $func, array $args = array()) + { + $args = (array)$args; + switch ($flag) { + case EventInterface::EV_READ: + return $this->addReadStream($fd, $func); + case EventInterface::EV_WRITE: + return $this->addWriteStream($fd, $func); + case EventInterface::EV_SIGNAL: + if (isset($this->_signalHandlerMap[$fd])) { + $this->removeSignal($fd, $this->_signalHandlerMap[$fd]); + } + $this->_signalHandlerMap[$fd] = $func; + return $this->addSignal($fd, $func); + case EventInterface::EV_TIMER: + $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) { + \call_user_func_array($func, $args); + }); + $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj; + return $this->_timerIdIndex; + case EventInterface::EV_TIMER_ONCE: + $index = ++$this->_timerIdIndex; + $timer_obj = $this->addTimer($fd, function() use ($func, $args, $index) { + $this->del($index,EventInterface::EV_TIMER_ONCE); + \call_user_func_array($func, $args); + }); + $this->_timerIdMap[$index] = $timer_obj; + return $this->_timerIdIndex; + } + return false; + } + + /** + * Remove event listener from event loop. + * + * @param mixed $fd + * @param int $flag + * @return bool + */ + public function del($fd, $flag) + { + switch ($flag) { + case EventInterface::EV_READ: + return $this->removeReadStream($fd); + case EventInterface::EV_WRITE: + return $this->removeWriteStream($fd); + case EventInterface::EV_SIGNAL: + if (!isset($this->_eventLoop[$fd])) { + return false; + } + $func = $this->_eventLoop[$fd]; + unset($this->_eventLoop[$fd]); + return $this->removeSignal($fd, $func); + + case EventInterface::EV_TIMER: + case EventInterface::EV_TIMER_ONCE: + if (isset($this->_timerIdMap[$fd])){ + $timer_obj = $this->_timerIdMap[$fd]; + unset($this->_timerIdMap[$fd]); + $this->cancelTimer($timer_obj); + return true; + } + } + return false; + } + + + /** + * Main loop. + * + * @return void + */ + public function loop() + { + $this->run(); + } + + + /** + * Destroy loop. + * + * @return void + */ + public function destroy() + { + + } + + /** + * Get timer count. + * + * @return integer + */ + public function getTimerCount() + { + return \count($this->_timerIdMap); + } + + /** + * @param resource $stream + * @param callable $listener + */ + public function addReadStream($stream, $listener) + { + return $this->_eventLoop->addReadStream($stream, $listener); + } + + /** + * @param resource $stream + * @param callable $listener + */ + public function addWriteStream($stream, $listener) + { + return $this->_eventLoop->addWriteStream($stream, $listener); + } + + /** + * @param resource $stream + */ + public function removeReadStream($stream) + { + return $this->_eventLoop->removeReadStream($stream); + } + + /** + * @param resource $stream + */ + public function removeWriteStream($stream) + { + return $this->_eventLoop->removeWriteStream($stream); + } + + /** + * @param float|int $interval + * @param callable $callback + * @return \React\EventLoop\Timer\Timer|TimerInterface + */ + public function addTimer($interval, $callback) + { + return $this->_eventLoop->addTimer($interval, $callback); + } + + /** + * @param float|int $interval + * @param callable $callback + * @return \React\EventLoop\Timer\Timer|TimerInterface + */ + public function addPeriodicTimer($interval, $callback) + { + return $this->_eventLoop->addPeriodicTimer($interval, $callback); + } + + /** + * @param TimerInterface $timer + */ + public function cancelTimer(TimerInterface $timer) + { + return $this->_eventLoop->cancelTimer($timer); + } + + /** + * @param callable $listener + */ + public function futureTick($listener) + { + return $this->_eventLoop->futureTick($listener); + } + + /** + * @param int $signal + * @param callable $listener + */ + public function addSignal($signal, $listener) + { + return $this->_eventLoop->addSignal($signal, $listener); + } + + /** + * @param int $signal + * @param callable $listener + */ + public function removeSignal($signal, $listener) + { + return $this->_eventLoop->removeSignal($signal, $listener); + } + + /** + * Run. + */ + public function run() + { + return $this->_eventLoop->run(); + } + + /** + * Stop. + */ + public function stop() + { + return $this->_eventLoop->stop(); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/React/ExtEventLoop.php b/cacme/vendor/workerman/workerman/Events/React/ExtEventLoop.php new file mode 100644 index 0000000..3dab25b --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/React/ExtEventLoop.php @@ -0,0 +1,27 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events\React; + +/** + * Class ExtEventLoop + * @package Workerman\Events\React + */ +class ExtEventLoop extends Base +{ + + public function __construct() + { + $this->_eventLoop = new \React\EventLoop\ExtEventLoop(); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/React/ExtLibEventLoop.php b/cacme/vendor/workerman/workerman/Events/React/ExtLibEventLoop.php new file mode 100644 index 0000000..eb02b35 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/React/ExtLibEventLoop.php @@ -0,0 +1,27 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events\React; +use Workerman\Events\EventInterface; + +/** + * Class ExtLibEventLoop + * @package Workerman\Events\React + */ +class ExtLibEventLoop extends Base +{ + public function __construct() + { + $this->_eventLoop = new \React\EventLoop\ExtLibeventLoop(); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/React/StreamSelectLoop.php b/cacme/vendor/workerman/workerman/Events/React/StreamSelectLoop.php new file mode 100644 index 0000000..7f5f94b --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/React/StreamSelectLoop.php @@ -0,0 +1,26 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events\React; + +/** + * Class StreamSelectLoop + * @package Workerman\Events\React + */ +class StreamSelectLoop extends Base +{ + public function __construct() + { + $this->_eventLoop = new \React\EventLoop\StreamSelectLoop(); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/Select.php b/cacme/vendor/workerman/workerman/Events/Select.php new file mode 100644 index 0000000..ebc263e --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/Select.php @@ -0,0 +1,357 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +use Throwable; +use Workerman\Worker; + +/** + * select eventloop + */ +class Select implements EventInterface +{ + /** + * All listeners for read/write event. + * + * @var array + */ + public $_allEvents = array(); + + /** + * Event listeners of signal. + * + * @var array + */ + public $_signalEvents = array(); + + /** + * Fds waiting for read event. + * + * @var array + */ + protected $_readFds = array(); + + /** + * Fds waiting for write event. + * + * @var array + */ + protected $_writeFds = array(); + + /** + * Fds waiting for except event. + * + * @var array + */ + protected $_exceptFds = array(); + + /** + * Timer scheduler. + * {['data':timer_id, 'priority':run_timestamp], ..} + * + * @var \SplPriorityQueue + */ + protected $_scheduler = null; + + /** + * All timer event listeners. + * [[func, args, flag, timer_interval], ..] + * + * @var array + */ + protected $_eventTimer = array(); + + /** + * Timer id. + * + * @var int + */ + protected $_timerId = 1; + + /** + * Select timeout. + * + * @var int + */ + protected $_selectTimeout = 100000000; + + /** + * Paired socket channels + * + * @var array + */ + protected $channel = array(); + + /** + * Construct. + */ + public function __construct() + { + // Init SplPriorityQueue. + $this->_scheduler = new \SplPriorityQueue(); + $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); + } + + /** + * {@inheritdoc} + */ + public function add($fd, $flag, $func, $args = array()) + { + switch ($flag) { + case self::EV_READ: + case self::EV_WRITE: + $count = $flag === self::EV_READ ? \count($this->_readFds) : \count($this->_writeFds); + if ($count >= 1024) { + echo "Warning: system call select exceeded the maximum number of connections 1024, please install event/libevent extension for more connections.\n"; + } else if (\DIRECTORY_SEPARATOR !== '/' && $count >= 256) { + echo "Warning: system call select exceeded the maximum number of connections 256.\n"; + } + $fd_key = (int)$fd; + $this->_allEvents[$fd_key][$flag] = array($func, $fd); + if ($flag === self::EV_READ) { + $this->_readFds[$fd_key] = $fd; + } else { + $this->_writeFds[$fd_key] = $fd; + } + break; + case self::EV_EXCEPT: + $fd_key = (int)$fd; + $this->_allEvents[$fd_key][$flag] = array($func, $fd); + $this->_exceptFds[$fd_key] = $fd; + break; + case self::EV_SIGNAL: + // Windows not support signal. + if(\DIRECTORY_SEPARATOR !== '/') { + return false; + } + $fd_key = (int)$fd; + $this->_signalEvents[$fd_key][$flag] = array($func, $fd); + \pcntl_signal($fd, array($this, 'signalHandler')); + break; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + $timer_id = $this->_timerId++; + $run_time = \microtime(true) + $fd; + $this->_scheduler->insert($timer_id, -$run_time); + $this->_eventTimer[$timer_id] = array($func, (array)$args, $flag, $fd); + $select_timeout = ($run_time - \microtime(true)) * 1000000; + $select_timeout = $select_timeout <= 0 ? 1 : $select_timeout; + if( $this->_selectTimeout > $select_timeout ){ + $this->_selectTimeout = (int) $select_timeout; + } + return $timer_id; + } + + return true; + } + + /** + * Signal handler. + * + * @param int $signal + */ + public function signalHandler($signal) + { + \call_user_func_array($this->_signalEvents[$signal][self::EV_SIGNAL][0], array($signal)); + } + + /** + * {@inheritdoc} + */ + public function del($fd, $flag) + { + $fd_key = (int)$fd; + switch ($flag) { + case self::EV_READ: + unset($this->_allEvents[$fd_key][$flag], $this->_readFds[$fd_key]); + if (empty($this->_allEvents[$fd_key])) { + unset($this->_allEvents[$fd_key]); + } + return true; + case self::EV_WRITE: + unset($this->_allEvents[$fd_key][$flag], $this->_writeFds[$fd_key]); + if (empty($this->_allEvents[$fd_key])) { + unset($this->_allEvents[$fd_key]); + } + return true; + case self::EV_EXCEPT: + unset($this->_allEvents[$fd_key][$flag], $this->_exceptFds[$fd_key]); + if(empty($this->_allEvents[$fd_key])) + { + unset($this->_allEvents[$fd_key]); + } + return true; + case self::EV_SIGNAL: + if(\DIRECTORY_SEPARATOR !== '/') { + return false; + } + unset($this->_signalEvents[$fd_key]); + \pcntl_signal($fd, SIG_IGN); + break; + case self::EV_TIMER: + case self::EV_TIMER_ONCE; + unset($this->_eventTimer[$fd_key]); + return true; + } + return false; + } + + /** + * Tick for timer. + * + * @return void + */ + protected function tick() + { + $tasks_to_insert = []; + while (!$this->_scheduler->isEmpty()) { + $scheduler_data = $this->_scheduler->top(); + $timer_id = $scheduler_data['data']; + $next_run_time = -$scheduler_data['priority']; + $time_now = \microtime(true); + $this->_selectTimeout = (int) (($next_run_time - $time_now) * 1000000); + if ($this->_selectTimeout <= 0) { + $this->_scheduler->extract(); + + if (!isset($this->_eventTimer[$timer_id])) { + continue; + } + + // [func, args, flag, timer_interval] + $task_data = $this->_eventTimer[$timer_id]; + if ($task_data[2] === self::EV_TIMER) { + $next_run_time = $time_now + $task_data[3]; + $tasks_to_insert[] = [$timer_id, -$next_run_time]; + } + try { + \call_user_func_array($task_data[0], $task_data[1]); + } catch (Throwable $e) { + Worker::stopAll(250, $e); + } + if (isset($this->_eventTimer[$timer_id]) && $task_data[2] === self::EV_TIMER_ONCE) { + $this->del($timer_id, self::EV_TIMER_ONCE); + } + } else { + break; + } + } + foreach ($tasks_to_insert as $item) { + $this->_scheduler->insert($item[0], $item[1]); + } + if (!$this->_scheduler->isEmpty()) { + $scheduler_data = $this->_scheduler->top(); + $next_run_time = -$scheduler_data['priority']; + $time_now = \microtime(true); + $this->_selectTimeout = \max((int) (($next_run_time - $time_now) * 1000000), 0); + return; + } + $this->_selectTimeout = 100000000; + } + + /** + * {@inheritdoc} + */ + public function clearAllTimer() + { + $this->_scheduler = new \SplPriorityQueue(); + $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); + $this->_eventTimer = array(); + } + + /** + * {@inheritdoc} + */ + public function loop() + { + while (1) { + if(\DIRECTORY_SEPARATOR === '/') { + // Calls signal handlers for pending signals + \pcntl_signal_dispatch(); + } + + $read = $this->_readFds; + $write = $this->_writeFds; + $except = $this->_exceptFds; + $ret = false; + + if ($read || $write || $except) { + // Waiting read/write/signal/timeout events. + try { + $ret = @stream_select($read, $write, $except, 0, $this->_selectTimeout); + } catch (\Exception $e) {} catch (\Error $e) {} + + } else { + $this->_selectTimeout >= 1 && usleep($this->_selectTimeout); + } + + if (!$this->_scheduler->isEmpty()) { + $this->tick(); + } + + if (!$ret) { + continue; + } + + if ($read) { + foreach ($read as $fd) { + $fd_key = (int)$fd; + if (isset($this->_allEvents[$fd_key][self::EV_READ])) { + \call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], + array($this->_allEvents[$fd_key][self::EV_READ][1])); + } + } + } + + if ($write) { + foreach ($write as $fd) { + $fd_key = (int)$fd; + if (isset($this->_allEvents[$fd_key][self::EV_WRITE])) { + \call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], + array($this->_allEvents[$fd_key][self::EV_WRITE][1])); + } + } + } + + if($except) { + foreach($except as $fd) { + $fd_key = (int) $fd; + if(isset($this->_allEvents[$fd_key][self::EV_EXCEPT])) { + \call_user_func_array($this->_allEvents[$fd_key][self::EV_EXCEPT][0], + array($this->_allEvents[$fd_key][self::EV_EXCEPT][1])); + } + } + } + } + } + + /** + * Destroy loop. + * + * @return void + */ + public function destroy() + { + + } + + /** + * Get timer count. + * + * @return integer + */ + public function getTimerCount() + { + return \count($this->_eventTimer); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/Swoole.php b/cacme/vendor/workerman/workerman/Events/Swoole.php new file mode 100644 index 0000000..fcd7472 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/Swoole.php @@ -0,0 +1,230 @@ + + * @link http://www.workerman.net/ + * @link https://github.com/ares333/Workerman + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +use Workerman\Worker; +use Swoole\Event; +use Swoole\Timer; + +class Swoole implements EventInterface +{ + + protected $_timer = array(); + + protected $_timerOnceMap = array(); + + protected $mapId = 0; + + protected $_fd = array(); + + // milisecond + public static $signalDispatchInterval = 500; + + protected $_hasSignal = false; + + /** + * + * {@inheritdoc} + * + * @see \Workerman\Events\EventInterface::add() + */ + public function add($fd, $flag, $func, $args = array()) + { + switch ($flag) { + case self::EV_SIGNAL: + $res = \pcntl_signal($fd, $func, false); + if (! $this->_hasSignal && $res) { + Timer::tick(static::$signalDispatchInterval, + function () { + \pcntl_signal_dispatch(); + }); + $this->_hasSignal = true; + } + return $res; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + $method = self::EV_TIMER === $flag ? 'tick' : 'after'; + if ($this->mapId > \PHP_INT_MAX) { + $this->mapId = 0; + } + $mapId = $this->mapId++; + $t = (int)($fd * 1000); + if ($t < 1) { + $t = 1; + } + $timer_id = Timer::$method($t, + function ($timer_id = null) use ($func, $args, $mapId) { + try { + \call_user_func_array($func, (array)$args); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + // EV_TIMER_ONCE + if (! isset($timer_id)) { + // may be deleted in $func + if (\array_key_exists($mapId, $this->_timerOnceMap)) { + $timer_id = $this->_timerOnceMap[$mapId]; + unset($this->_timer[$timer_id], + $this->_timerOnceMap[$mapId]); + } + } + }); + if ($flag === self::EV_TIMER_ONCE) { + $this->_timerOnceMap[$mapId] = $timer_id; + $this->_timer[$timer_id] = $mapId; + } else { + $this->_timer[$timer_id] = null; + } + return $timer_id; + case self::EV_READ: + case self::EV_WRITE: + $fd_key = (int) $fd; + if (! isset($this->_fd[$fd_key])) { + if ($flag === self::EV_READ) { + $res = Event::add($fd, $func, null, SWOOLE_EVENT_READ); + $fd_type = SWOOLE_EVENT_READ; + } else { + $res = Event::add($fd, null, $func, SWOOLE_EVENT_WRITE); + $fd_type = SWOOLE_EVENT_WRITE; + } + if ($res) { + $this->_fd[$fd_key] = $fd_type; + } + } else { + $fd_val = $this->_fd[$fd_key]; + $res = true; + if ($flag === self::EV_READ) { + if (($fd_val & SWOOLE_EVENT_READ) !== SWOOLE_EVENT_READ) { + $res = Event::set($fd, $func, null, + SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE); + $this->_fd[$fd_key] |= SWOOLE_EVENT_READ; + } + } else { + if (($fd_val & SWOOLE_EVENT_WRITE) !== SWOOLE_EVENT_WRITE) { + $res = Event::set($fd, null, $func, + SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE); + $this->_fd[$fd_key] |= SWOOLE_EVENT_WRITE; + } + } + } + return $res; + } + } + + /** + * + * {@inheritdoc} + * + * @see \Workerman\Events\EventInterface::del() + */ + public function del($fd, $flag) + { + switch ($flag) { + case self::EV_SIGNAL: + return \pcntl_signal($fd, SIG_IGN, false); + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + // already remove in EV_TIMER_ONCE callback. + if (! \array_key_exists($fd, $this->_timer)) { + return true; + } + $res = Timer::clear($fd); + if ($res) { + $mapId = $this->_timer[$fd]; + if (isset($mapId)) { + unset($this->_timerOnceMap[$mapId]); + } + unset($this->_timer[$fd]); + } + return $res; + case self::EV_READ: + case self::EV_WRITE: + $fd_key = (int) $fd; + if (isset($this->_fd[$fd_key])) { + $fd_val = $this->_fd[$fd_key]; + if ($flag === self::EV_READ) { + $flag_remove = ~ SWOOLE_EVENT_READ; + } else { + $flag_remove = ~ SWOOLE_EVENT_WRITE; + } + $fd_val &= $flag_remove; + if (0 === $fd_val) { + $res = Event::del($fd); + if ($res) { + unset($this->_fd[$fd_key]); + } + } else { + $res = Event::set($fd, null, null, $fd_val); + if ($res) { + $this->_fd[$fd_key] = $fd_val; + } + } + } else { + $res = true; + } + return $res; + } + } + + /** + * + * {@inheritdoc} + * + * @see \Workerman\Events\EventInterface::clearAllTimer() + */ + public function clearAllTimer() + { + foreach (array_keys($this->_timer) as $v) { + Timer::clear($v); + } + $this->_timer = array(); + $this->_timerOnceMap = array(); + } + + /** + * + * {@inheritdoc} + * + * @see \Workerman\Events\EventInterface::loop() + */ + public function loop() + { + Event::wait(); + } + + /** + * + * {@inheritdoc} + * + * @see \Workerman\Events\EventInterface::destroy() + */ + public function destroy() + { + Event::exit(); + posix_kill(posix_getpid(), SIGINT); + } + + /** + * + * {@inheritdoc} + * + * @see \Workerman\Events\EventInterface::getTimerCount() + */ + public function getTimerCount() + { + return \count($this->_timer); + } +} diff --git a/cacme/vendor/workerman/workerman/Events/Uv.php b/cacme/vendor/workerman/workerman/Events/Uv.php new file mode 100644 index 0000000..49f0ddd --- /dev/null +++ b/cacme/vendor/workerman/workerman/Events/Uv.php @@ -0,0 +1,260 @@ + + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Events; + +use Workerman\Worker; + +/** + * libuv eventloop + */ +class Uv implements EventInterface +{ + /** + * Event Loop. + * @var object + */ + protected $_eventLoop = null; + + /** + * All listeners for read/write event. + * + * @var array + */ + protected $_allEvents = array(); + + /** + * Event listeners of signal. + * + * @var array + */ + protected $_eventSignal = array(); + + /** + * All timer event listeners. + * + * @var array + */ + protected $_eventTimer = array(); + + /** + * Timer id. + * + * @var int + */ + protected static $_timerId = 1; + + /** + * @brief Constructor + * + * @param object $loop + * + * @return void + */ + public function __construct(\UVLoop $loop = null) + { + if(!extension_loaded('uv')) + { + throw new \Exception(__CLASS__ . ' requires the UV extension, but detected it has NOT been installed yet.'); + } + + if(empty($loop) || !$loop instanceof \UVLoop) + { + $this->_eventLoop = \uv_default_loop(); + return; + } + + $this->_eventLoop = $loop; + } + + /** + * @brief Add a timer + * + * @param resource $fd + * @param int $flag + * @param callback $func + * @param mixed $args + * + * @return mixed + */ + public function add($fd, $flag, $func, $args = null) + { + switch ($flag) + { + case self::EV_SIGNAL: + $signalCallback = function($watcher, $socket)use($func, $fd){ + try { + \call_user_func($func, $fd); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + }; + $signalWatcher = \uv_signal_init(); + \uv_signal_start($signalWatcher, $signalCallback, $fd); + $this->_eventSignal[$fd] = $signalWatcher; + return true; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + $repeat = $flag === self::EV_TIMER_ONCE ? 0 : (int)($fd * 1000); + $param = array($func, (array)$args, $flag, $fd, self::$_timerId); + $timerWatcher = \uv_timer_init(); + \uv_timer_start($timerWatcher, ($flag === self::EV_TIMER_ONCE ? (int)($fd * 1000) :1), $repeat, function($watcher)use($param){ + call_user_func_array([$this, 'timerCallback'], [$param]); + }); + $this->_eventTimer[self::$_timerId] = $timerWatcher; + return self::$_timerId++; + case self::EV_READ: + case self::EV_WRITE: + $fd_key = (int)$fd; + $ioCallback = function($watcher, $status, $events, $fd)use($func){ + try { + \call_user_func($func, $fd); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + }; + $ioWatcher = \uv_poll_init($this->_eventLoop, $fd); + $real_flag = $flag === self::EV_READ ? \Uv::READABLE : \Uv::WRITABLE; + \uv_poll_start($ioWatcher, $real_flag, $ioCallback); + $this->_allEvents[$fd_key][$flag] = $ioWatcher; + return true; + default: + break; + } + } + + /** + * @brief Remove a timer + * + * @param resource $fd + * @param int $flag + * + * @return boolean + */ + public function del($fd, $flag) + { + switch ($flag) + { + case self::EV_READ: + case self::EV_WRITE: + $fd_key = (int)$fd; + if (isset($this->_allEvents[$fd_key][$flag])) { + $watcher = $this->_allEvents[$fd_key][$flag]; + \uv_is_active($watcher) && \uv_poll_stop($watcher); + unset($this->_allEvents[$fd_key][$flag]); + } + if (empty($this->_allEvents[$fd_key])) { + unset($this->_allEvents[$fd_key]); + } + break; + case self::EV_SIGNAL: + $fd_key = (int)$fd; + if (isset($this->_eventSignal[$fd_key])) { + $watcher = $this->_eventSignal[$fd_key]; + \uv_is_active($watcher) && \uv_signal_stop($watcher); + unset($this->_eventSignal[$fd_key]); + } + break; + case self::EV_TIMER: + case self::EV_TIMER_ONCE: + if (isset($this->_eventTimer[$fd])) { + $watcher = $this->_eventTimer[$fd]; + \uv_is_active($watcher) && \uv_timer_stop($watcher); + unset($this->_eventTimer[$fd]); + } + break; + } + + return true; + } + + /** + * @brief Timer callback + * + * @param array $input + * + * @return void + */ + public function timerCallback($input) + { + if(!is_array($input)) return; + + $timer_id = $input[4]; + + if ($input[2] === self::EV_TIMER_ONCE) + { + $watcher = $this->_eventTimer[$timer_id]; + \uv_is_active($watcher) && \uv_timer_stop($watcher); + unset($this->_eventTimer[$timer_id]); + } + + try { + \call_user_func_array($input[0], $input[1]); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + } + + /** + * @brief Remove all timers + * + * @return void + */ + public function clearAllTimer() + { + if(!is_array($this->_eventTimer)) return; + + foreach($this->_eventTimer as $watcher) + { + \uv_is_active($watcher) && \uv_timer_stop($watcher); + } + + $this->_eventTimer = array(); + } + + /** + * @brief Start loop + * + * @return void + */ + public function loop() + { + \Uv_run(); + } + + /** + * @brief Destroy loop + * + * @return void + */ + public function destroy() + { + !empty($this->_eventLoop) && \uv_loop_delete($this->_eventLoop); + $this->_allEvents = []; + } + + /** + * @brief Get timer count + * + * @return integer + */ + public function getTimerCount() + { + return \count($this->_eventTimer); + } +} diff --git a/cacme/vendor/workerman/workerman/Lib/Constants.php b/cacme/vendor/workerman/workerman/Lib/Constants.php new file mode 100644 index 0000000..f5e2424 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Lib/Constants.php @@ -0,0 +1,44 @@ + + * @copyright walkor + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * + * @link http://www.workerman.net/ + */ + +// Pcre.jit is not stable, temporarily disabled. +ini_set('pcre.jit', 0); + +// For onError callback. +const WORKERMAN_CONNECT_FAIL = 1; +// For onError callback. +const WORKERMAN_SEND_FAIL = 2; + +// Define OS Type +const OS_TYPE_LINUX = 'linux'; +const OS_TYPE_WINDOWS = 'windows'; + +// Compatible with php7 +if (!class_exists('Error')) { + class Error extends Exception + { + } +} + +if (!interface_exists('SessionHandlerInterface')) { + interface SessionHandlerInterface { + public function close(); + public function destroy($session_id); + public function gc($maxlifetime); + public function open($save_path ,$session_name); + public function read($session_id); + public function write($session_id , $session_data); + } +} diff --git a/cacme/vendor/workerman/workerman/Lib/Timer.php b/cacme/vendor/workerman/workerman/Lib/Timer.php new file mode 100644 index 0000000..b110051 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Lib/Timer.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Lib; + +/** + * Do not use Workerman\Lib\Timer. + * Please use Workerman\Timer. + * This class is only used for compatibility with workerman 3.* + * @package Workerman\Lib + */ +class Timer extends \Workerman\Timer {} \ No newline at end of file diff --git a/cacme/vendor/workerman/workerman/MIT-LICENSE.txt b/cacme/vendor/workerman/workerman/MIT-LICENSE.txt new file mode 100644 index 0000000..fd6b1c8 --- /dev/null +++ b/cacme/vendor/workerman/workerman/MIT-LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2009-2015 walkor and contributors (see https://github.com/walkor/workerman/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/cacme/vendor/workerman/workerman/Protocols/Frame.php b/cacme/vendor/workerman/workerman/Protocols/Frame.php new file mode 100644 index 0000000..26b04de --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Frame.php @@ -0,0 +1,61 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols; + +use Workerman\Connection\TcpConnection; + +/** + * Frame Protocol. + */ +class Frame +{ + /** + * Check the integrity of the package. + * + * @param string $buffer + * @param TcpConnection $connection + * @return int + */ + public static function input($buffer, TcpConnection $connection) + { + if (\strlen($buffer) < 4) { + return 0; + } + $unpack_data = \unpack('Ntotal_length', $buffer); + return $unpack_data['total_length']; + } + + /** + * Decode. + * + * @param string $buffer + * @return string + */ + public static function decode($buffer) + { + return \substr($buffer, 4); + } + + /** + * Encode. + * + * @param string $buffer + * @return string + */ + public static function encode($buffer) + { + $total_length = 4 + \strlen($buffer); + return \pack('N', $total_length) . $buffer; + } +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Http.php b/cacme/vendor/workerman/workerman/Protocols/Http.php new file mode 100644 index 0000000..9e5d928 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http.php @@ -0,0 +1,323 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols; + +use Workerman\Connection\TcpConnection; +use Workerman\Protocols\Http\Request; +use Workerman\Protocols\Http\Response; +use Workerman\Protocols\Http\Session; +use Workerman\Protocols\Websocket; +use Workerman\Worker; + +/** + * Class Http. + * @package Workerman\Protocols + */ +class Http +{ + /** + * Request class name. + * + * @var string + */ + protected static $_requestClass = 'Workerman\Protocols\Http\Request'; + + /** + * Upload tmp dir. + * + * @var string + */ + protected static $_uploadTmpDir = ''; + + /** + * Open cache. + * + * @var bool. + */ + protected static $_enableCache = true; + + /** + * Get or set session name. + * + * @param string|null $name + * @return string + */ + public static function sessionName($name = null) + { + if ($name !== null && $name !== '') { + Session::$name = (string)$name; + } + return Session::$name; + } + + /** + * Get or set the request class name. + * + * @param string|null $class_name + * @return string + */ + public static function requestClass($class_name = null) + { + if ($class_name) { + static::$_requestClass = $class_name; + } + return static::$_requestClass; + } + + /** + * Enable or disable Cache. + * + * @param mixed $value + */ + public static function enableCache($value) + { + static::$_enableCache = (bool)$value; + } + + /** + * Check the integrity of the package. + * + * @param string $recv_buffer + * @param TcpConnection $connection + * @return int + */ + public static function input($recv_buffer, TcpConnection $connection) + { + static $input = []; + if (!isset($recv_buffer[512]) && isset($input[$recv_buffer])) { + return $input[$recv_buffer]; + } + $crlf_pos = \strpos($recv_buffer, "\r\n\r\n"); + if (false === $crlf_pos) { + // Judge whether the package length exceeds the limit. + if (\strlen($recv_buffer) >= 16384) { + $connection->close("HTTP/1.1 413 Request Entity Too Large\r\n\r\n", true); + return 0; + } + return 0; + } + + $length = $crlf_pos + 4; + $method = \strstr($recv_buffer, ' ', true); + + if (!\in_array($method, ['GET', 'POST', 'OPTIONS', 'HEAD', 'DELETE', 'PUT', 'PATCH'])) { + $connection->close("HTTP/1.1 400 Bad Request\r\n\r\n", true); + return 0; + } + + $header = \substr($recv_buffer, 0, $crlf_pos); + if ($pos = \strpos($header, "\r\nContent-Length: ")) { + $length = $length + (int)\substr($header, $pos + 18, 10); + $has_content_length = true; + } else if (\preg_match("/\r\ncontent-length: ?(\d+)/i", $header, $match)) { + $length = $length + $match[1]; + $has_content_length = true; + } else { + $has_content_length = false; + if (false !== stripos($header, "\r\nTransfer-Encoding:")) { + $connection->close("HTTP/1.1 400 Bad Request\r\n\r\n", true); + return 0; + } + } + + if ($has_content_length) { + if ($length > $connection->maxPackageSize) { + $connection->close("HTTP/1.1 413 Request Entity Too Large\r\n\r\n", true); + return 0; + } + } + + if (!isset($recv_buffer[512])) { + $input[$recv_buffer] = $length; + if (\count($input) > 512) { + unset($input[key($input)]); + } + } + + return $length; + } + + /** + * Http decode. + * + * @param string $recv_buffer + * @param TcpConnection $connection + * @return \Workerman\Protocols\Http\Request + */ + public static function decode($recv_buffer, TcpConnection $connection) + { + static $requests = array(); + $cacheable = static::$_enableCache && !isset($recv_buffer[512]); + if (true === $cacheable && isset($requests[$recv_buffer])) { + $request = $requests[$recv_buffer]; + $request->connection = $connection; + $connection->__request = $request; + $request->properties = array(); + return $request; + } + $request = new static::$_requestClass($recv_buffer); + $request->connection = $connection; + $connection->__request = $request; + if (true === $cacheable) { + $requests[$recv_buffer] = $request; + if (\count($requests) > 512) { + unset($requests[key($requests)]); + } + } + return $request; + } + + /** + * Http encode. + * + * @param string|Response $response + * @param TcpConnection $connection + * @return string + */ + public static function encode($response, TcpConnection $connection) + { + if (isset($connection->__request)) { + $connection->__request->session = null; + $connection->__request->connection = null; + $connection->__request = null; + } + if (!\is_object($response)) { + $ext_header = ''; + if (isset($connection->__header)) { + foreach ($connection->__header as $name => $value) { + if (\is_array($value)) { + foreach ($value as $item) { + $ext_header = "$name: $item\r\n"; + } + } else { + $ext_header = "$name: $value\r\n"; + } + } + unset($connection->__header); + } + $body_len = \strlen((string)$response); + return "HTTP/1.1 200 OK\r\nServer: workerman\r\n{$ext_header}Connection: keep-alive\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: $body_len\r\n\r\n$response"; + } + + if (isset($connection->__header)) { + $response->withHeaders($connection->__header); + unset($connection->__header); + } + + if (isset($response->file)) { + $file = $response->file['file']; + $offset = $response->file['offset']; + $length = $response->file['length']; + clearstatcache(); + $file_size = (int)\filesize($file); + $body_len = $length > 0 ? $length : $file_size - $offset; + $response->withHeaders(array( + 'Content-Length' => $body_len, + 'Accept-Ranges' => 'bytes', + )); + if ($offset || $length) { + $offset_end = $offset + $body_len - 1; + $response->header('Content-Range', "bytes $offset-$offset_end/$file_size"); + } + if ($body_len < 2 * 1024 * 1024) { + $connection->send((string)$response . file_get_contents($file, false, null, $offset, $body_len), true); + return ''; + } + $handler = \fopen($file, 'r'); + if (false === $handler) { + $connection->close(new Response(403, null, '403 Forbidden')); + return ''; + } + $connection->send((string)$response, true); + static::sendStream($connection, $handler, $offset, $length); + return ''; + } + + return (string)$response; + } + + /** + * Send remainder of a stream to client. + * + * @param TcpConnection $connection + * @param resource $handler + * @param int $offset + * @param int $length + */ + protected static function sendStream(TcpConnection $connection, $handler, $offset = 0, $length = 0) + { + $connection->bufferFull = false; + if ($offset !== 0) { + \fseek($handler, $offset); + } + $offset_end = $offset + $length; + // Read file content from disk piece by piece and send to client. + $do_write = function () use ($connection, $handler, $length, $offset_end) { + // Send buffer not full. + while ($connection->bufferFull === false) { + // Read from disk. + $size = 1024 * 1024; + if ($length !== 0) { + $tell = \ftell($handler); + $remain_size = $offset_end - $tell; + if ($remain_size <= 0) { + fclose($handler); + $connection->onBufferDrain = null; + return; + } + $size = $remain_size > $size ? $size : $remain_size; + } + + $buffer = \fread($handler, $size); + // Read eof. + if ($buffer === '' || $buffer === false) { + fclose($handler); + $connection->onBufferDrain = null; + return; + } + $connection->send($buffer, true); + } + }; + // Send buffer full. + $connection->onBufferFull = function ($connection) { + $connection->bufferFull = true; + }; + // Send buffer drain. + $connection->onBufferDrain = function ($connection) use ($do_write) { + $connection->bufferFull = false; + $do_write(); + }; + $do_write(); + } + + /** + * Set or get uploadTmpDir. + * + * @return bool|string + */ + public static function uploadTmpDir($dir = null) + { + if (null !== $dir) { + static::$_uploadTmpDir = $dir; + } + if (static::$_uploadTmpDir === '') { + if ($upload_tmp_dir = \ini_get('upload_tmp_dir')) { + static::$_uploadTmpDir = $upload_tmp_dir; + } else if ($upload_tmp_dir = \sys_get_temp_dir()) { + static::$_uploadTmpDir = $upload_tmp_dir; + } + } + return static::$_uploadTmpDir; + } +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Chunk.php b/cacme/vendor/workerman/workerman/Protocols/Http/Chunk.php new file mode 100644 index 0000000..ab06a9c --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Chunk.php @@ -0,0 +1,48 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http; + + +/** + * Class Chunk + * @package Workerman\Protocols\Http + */ +class Chunk +{ + /** + * Chunk buffer. + * + * @var string + */ + protected $_buffer = null; + + /** + * Chunk constructor. + * @param string $buffer + */ + public function __construct($buffer) + { + $this->_buffer = $buffer; + } + + /** + * __toString + * + * @return string + */ + public function __toString() + { + return \dechex(\strlen($this->_buffer))."\r\n$this->_buffer\r\n"; + } +} \ No newline at end of file diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Request.php b/cacme/vendor/workerman/workerman/Protocols/Http/Request.php new file mode 100644 index 0000000..d544ac0 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Request.php @@ -0,0 +1,694 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http; + +use Workerman\Connection\TcpConnection; +use Workerman\Protocols\Http\Session; +use Workerman\Protocols\Http; +use Workerman\Worker; + +/** + * Class Request + * @package Workerman\Protocols\Http + */ +class Request +{ + /** + * Connection. + * + * @var TcpConnection + */ + public $connection = null; + + /** + * Session instance. + * + * @var Session + */ + public $session = null; + + /** + * Properties. + * + * @var array + */ + public $properties = array(); + + /** + * @var int + */ + public static $maxFileUploads = 1024; + + /** + * Http buffer. + * + * @var string + */ + protected $_buffer = null; + + /** + * Request data. + * + * @var array + */ + protected $_data = null; + + /** + * Enable cache. + * + * @var bool + */ + protected static $_enableCache = true; + + /** + * Is safe. + * + * @var bool + */ + protected $_isSafe = true; + + + /** + * Request constructor. + * + * @param string $buffer + */ + public function __construct($buffer) + { + $this->_buffer = $buffer; + } + + /** + * $_GET. + * + * @param string|null $name + * @param mixed|null $default + * @return mixed|null + */ + public function get($name = null, $default = null) + { + if (!isset($this->_data['get'])) { + $this->parseGet(); + } + if (null === $name) { + return $this->_data['get']; + } + return isset($this->_data['get'][$name]) ? $this->_data['get'][$name] : $default; + } + + /** + * $_POST. + * + * @param string|null $name + * @param mixed|null $default + * @return mixed|null + */ + public function post($name = null, $default = null) + { + if (!isset($this->_data['post'])) { + $this->parsePost(); + } + if (null === $name) { + return $this->_data['post']; + } + return isset($this->_data['post'][$name]) ? $this->_data['post'][$name] : $default; + } + + /** + * Get header item by name. + * + * @param string|null $name + * @param mixed|null $default + * @return array|string|null + */ + public function header($name = null, $default = null) + { + if (!isset($this->_data['headers'])) { + $this->parseHeaders(); + } + if (null === $name) { + return $this->_data['headers']; + } + $name = \strtolower($name); + return isset($this->_data['headers'][$name]) ? $this->_data['headers'][$name] : $default; + } + + /** + * Get cookie item by name. + * + * @param string|null $name + * @param mixed|null $default + * @return array|string|null + */ + public function cookie($name = null, $default = null) + { + if (!isset($this->_data['cookie'])) { + $this->_data['cookie'] = array(); + \parse_str(\preg_replace('/; ?/', '&', $this->header('cookie', '')), $this->_data['cookie']); + } + if ($name === null) { + return $this->_data['cookie']; + } + return isset($this->_data['cookie'][$name]) ? $this->_data['cookie'][$name] : $default; + } + + /** + * Get upload files. + * + * @param string|null $name + * @return array|null + */ + public function file($name = null) + { + if (!isset($this->_data['files'])) { + $this->parsePost(); + } + if (null === $name) { + return $this->_data['files']; + } + return isset($this->_data['files'][$name]) ? $this->_data['files'][$name] : null; + } + + /** + * Get method. + * + * @return string + */ + public function method() + { + if (!isset($this->_data['method'])) { + $this->parseHeadFirstLine(); + } + return $this->_data['method']; + } + + /** + * Get http protocol version. + * + * @return string + */ + public function protocolVersion() + { + if (!isset($this->_data['protocolVersion'])) { + $this->parseProtocolVersion(); + } + return $this->_data['protocolVersion']; + } + + /** + * Get host. + * + * @param bool $without_port + * @return string + */ + public function host($without_port = false) + { + $host = $this->header('host'); + if ($host && $without_port) { + return preg_replace('/:\d{1,5}$/', '', $host); + } + return $host; + } + + /** + * Get uri. + * + * @return mixed + */ + public function uri() + { + if (!isset($this->_data['uri'])) { + $this->parseHeadFirstLine(); + } + return $this->_data['uri']; + } + + /** + * Get path. + * + * @return mixed + */ + public function path() + { + if (!isset($this->_data['path'])) { + $this->_data['path'] = (string)\parse_url($this->uri(), PHP_URL_PATH); + } + return $this->_data['path']; + } + + /** + * Get query string. + * + * @return mixed + */ + public function queryString() + { + if (!isset($this->_data['query_string'])) { + $this->_data['query_string'] = (string)\parse_url($this->uri(), PHP_URL_QUERY); + } + return $this->_data['query_string']; + } + + /** + * Get session. + * + * @return bool|\Workerman\Protocols\Http\Session + */ + public function session() + { + if ($this->session === null) { + $session_id = $this->sessionId(); + if ($session_id === false) { + return false; + } + $this->session = new Session($session_id); + } + return $this->session; + } + + /** + * Get/Set session id. + * + * @param $session_id + * @return string + */ + public function sessionId($session_id = null) + { + if ($session_id) { + unset($this->sid); + } + if (!isset($this->sid)) { + $session_name = Session::$name; + $sid = $session_id ? '' : $this->cookie($session_name); + if ($sid === '' || $sid === null) { + if ($this->connection === null) { + Worker::safeEcho('Request->session() fail, header already send'); + return false; + } + $sid = $session_id ? $session_id : static::createSessionId(); + $cookie_params = Session::getCookieParams(); + $this->connection->__header['Set-Cookie'] = array($session_name . '=' . $sid + . (empty($cookie_params['domain']) ? '' : '; Domain=' . $cookie_params['domain']) + . (empty($cookie_params['lifetime']) ? '' : '; Max-Age=' . $cookie_params['lifetime']) + . (empty($cookie_params['path']) ? '' : '; Path=' . $cookie_params['path']) + . (empty($cookie_params['samesite']) ? '' : '; SameSite=' . $cookie_params['samesite']) + . (!$cookie_params['secure'] ? '' : '; Secure') + . (!$cookie_params['httponly'] ? '' : '; HttpOnly')); + } + $this->sid = $sid; + } + return $this->sid; + } + + /** + * Get http raw head. + * + * @return string + */ + public function rawHead() + { + if (!isset($this->_data['head'])) { + $this->_data['head'] = \strstr($this->_buffer, "\r\n\r\n", true); + } + return $this->_data['head']; + } + + /** + * Get http raw body. + * + * @return string + */ + public function rawBody() + { + return \substr($this->_buffer, \strpos($this->_buffer, "\r\n\r\n") + 4); + } + + /** + * Get raw buffer. + * + * @return string + */ + public function rawBuffer() + { + return $this->_buffer; + } + + /** + * Enable or disable cache. + * + * @param mixed $value + */ + public static function enableCache($value) + { + static::$_enableCache = (bool)$value; + } + + /** + * Parse first line of http header buffer. + * + * @return void + */ + protected function parseHeadFirstLine() + { + $first_line = \strstr($this->_buffer, "\r\n", true); + $tmp = \explode(' ', $first_line, 3); + $this->_data['method'] = $tmp[0]; + $this->_data['uri'] = isset($tmp[1]) ? $tmp[1] : '/'; + } + + /** + * Parse protocol version. + * + * @return void + */ + protected function parseProtocolVersion() + { + $first_line = \strstr($this->_buffer, "\r\n", true); + $protoco_version = substr(\strstr($first_line, 'HTTP/'), 5); + $this->_data['protocolVersion'] = $protoco_version ? $protoco_version : '1.0'; + } + + /** + * Parse headers. + * + * @return void + */ + protected function parseHeaders() + { + static $cache = []; + $this->_data['headers'] = array(); + $raw_head = $this->rawHead(); + $end_line_position = \strpos($raw_head, "\r\n"); + if ($end_line_position === false) { + return; + } + $head_buffer = \substr($raw_head, $end_line_position + 2); + $cacheable = static::$_enableCache && !isset($head_buffer[2048]); + if ($cacheable && isset($cache[$head_buffer])) { + $this->_data['headers'] = $cache[$head_buffer]; + return; + } + $head_data = \explode("\r\n", $head_buffer); + foreach ($head_data as $content) { + if (false !== \strpos($content, ':')) { + list($key, $value) = \explode(':', $content, 2); + $key = \strtolower($key); + $value = \ltrim($value); + } else { + $key = \strtolower($content); + $value = ''; + } + if (isset($this->_data['headers'][$key])) { + $this->_data['headers'][$key] = "{$this->_data['headers'][$key]},$value"; + } else { + $this->_data['headers'][$key] = $value; + } + } + if ($cacheable) { + $cache[$head_buffer] = $this->_data['headers']; + if (\count($cache) > 128) { + unset($cache[key($cache)]); + } + } + } + + /** + * Parse head. + * + * @return void + */ + protected function parseGet() + { + static $cache = []; + $query_string = $this->queryString(); + $this->_data['get'] = array(); + if ($query_string === '') { + return; + } + $cacheable = static::$_enableCache && !isset($query_string[1024]); + if ($cacheable && isset($cache[$query_string])) { + $this->_data['get'] = $cache[$query_string]; + return; + } + \parse_str($query_string, $this->_data['get']); + if ($cacheable) { + $cache[$query_string] = $this->_data['get']; + if (\count($cache) > 256) { + unset($cache[key($cache)]); + } + } + } + + /** + * Parse post. + * + * @return void + */ + protected function parsePost() + { + static $cache = []; + $this->_data['post'] = $this->_data['files'] = array(); + $content_type = $this->header('content-type', ''); + if (\preg_match('/boundary="?(\S+)"?/', $content_type, $match)) { + $http_post_boundary = '--' . $match[1]; + $this->parseUploadFiles($http_post_boundary); + return; + } + $body_buffer = $this->rawBody(); + if ($body_buffer === '') { + return; + } + $cacheable = static::$_enableCache && !isset($body_buffer[1024]); + if ($cacheable && isset($cache[$body_buffer])) { + $this->_data['post'] = $cache[$body_buffer]; + return; + } + if (\preg_match('/\bjson\b/i', $content_type)) { + $this->_data['post'] = (array) json_decode($body_buffer, true); + } else { + \parse_str($body_buffer, $this->_data['post']); + } + if ($cacheable) { + $cache[$body_buffer] = $this->_data['post']; + if (\count($cache) > 256) { + unset($cache[key($cache)]); + } + } + } + + /** + * Parse upload files. + * + * @param string $http_post_boundary + * @return void + */ + protected function parseUploadFiles($http_post_boundary) + { + $http_post_boundary = \trim($http_post_boundary, '"'); + $buffer = $this->_buffer; + $post_encode_string = ''; + $files_encode_string = ''; + $files = []; + $boday_position = strpos($buffer, "\r\n\r\n") + 4; + $offset = $boday_position + strlen($http_post_boundary) + 2; + $max_count = static::$maxFileUploads; + while ($max_count-- > 0 && $offset) { + $offset = $this->parseUploadFile($http_post_boundary, $offset, $post_encode_string, $files_encode_string, $files); + } + if ($post_encode_string) { + parse_str($post_encode_string, $this->_data['post']); + } + + if ($files_encode_string) { + parse_str($files_encode_string, $this->_data['files']); + \array_walk_recursive($this->_data['files'], function (&$value) use ($files) { + $value = $files[$value]; + }); + } + } + + /** + * @param $boundary + * @param $section_start_offset + * @return int + */ + protected function parseUploadFile($boundary, $section_start_offset, &$post_encode_string, &$files_encode_str, &$files) + { + $file = []; + $boundary = "\r\n$boundary"; + if (\strlen($this->_buffer) < $section_start_offset) { + return 0; + } + $section_end_offset = \strpos($this->_buffer, $boundary, $section_start_offset); + if (!$section_end_offset) { + return 0; + } + $content_lines_end_offset = \strpos($this->_buffer, "\r\n\r\n", $section_start_offset); + if (!$content_lines_end_offset || $content_lines_end_offset + 4 > $section_end_offset) { + return 0; + } + $content_lines_str = \substr($this->_buffer, $section_start_offset, $content_lines_end_offset - $section_start_offset); + $content_lines = \explode("\r\n", trim($content_lines_str . "\r\n")); + $boundary_value = \substr($this->_buffer, $content_lines_end_offset + 4, $section_end_offset - $content_lines_end_offset - 4); + $upload_key = false; + foreach ($content_lines as $content_line) { + if (!\strpos($content_line, ': ')) { + return 0; + } + list($key, $value) = \explode(': ', $content_line); + switch (strtolower($key)) { + case "content-disposition": + // Is file data. + if (\preg_match('/name="(.*?)"; filename="(.*?)"/i', $value, $match)) { + $error = 0; + $tmp_file = ''; + $file_name = $match[2]; + $size = \strlen($boundary_value); + $tmp_upload_dir = HTTP::uploadTmpDir(); + if (!$tmp_upload_dir) { + $error = UPLOAD_ERR_NO_TMP_DIR; + } else if ($boundary_value === '' && $file_name === '') { + $error = UPLOAD_ERR_NO_FILE; + } else { + $tmp_file = \tempnam($tmp_upload_dir, 'workerman.upload.'); + if ($tmp_file === false || false === \file_put_contents($tmp_file, $boundary_value)) { + $error = UPLOAD_ERR_CANT_WRITE; + } + } + $upload_key = $match[1]; + // Parse upload files. + $file = [ + 'name' => $file_name, + 'tmp_name' => $tmp_file, + 'size' => $size, + 'error' => $error, + 'type' => '', + ]; + break; + } // Is post field. + else { + // Parse $_POST. + if (\preg_match('/name="(.*?)"$/', $value, $match)) { + $k = $match[1]; + $post_encode_string .= \urlencode($k) . "=" . \urlencode($boundary_value) . '&'; + } + return $section_end_offset + \strlen($boundary) + 2; + } + break; + case "content-type": + $file['type'] = \trim($value); + break; + } + } + if ($upload_key === false) { + return 0; + } + $files_encode_str .= \urlencode($upload_key) . '=' . \count($files) . '&'; + $files[] = $file; + + return $section_end_offset + \strlen($boundary) + 2; + } + + /** + * Create session id. + * + * @return string + */ + protected static function createSessionId() + { + return \bin2hex(\pack('d', \microtime(true)) . random_bytes(8)); + } + + /** + * Setter. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function __set($name, $value) + { + $this->properties[$name] = $value; + } + + /** + * Getter. + * + * @param string $name + * @return mixed|null + */ + public function __get($name) + { + return isset($this->properties[$name]) ? $this->properties[$name] : null; + } + + /** + * Isset. + * + * @param string $name + * @return bool + */ + public function __isset($name) + { + return isset($this->properties[$name]); + } + + /** + * Unset. + * + * @param string $name + * @return void + */ + public function __unset($name) + { + unset($this->properties[$name]); + } + + /** + * __toString. + */ + public function __toString() + { + return $this->_buffer; + } + + /** + * __wakeup. + * + * @return void + */ + public function __wakeup() + { + $this->_isSafe = false; + } + + /** + * __destruct. + * + * @return void + */ + public function __destruct() + { + if (isset($this->_data['files']) && $this->_isSafe) { + \clearstatcache(); + \array_walk_recursive($this->_data['files'], function($value, $key){ + if ($key === 'tmp_name') { + if (\is_file($value)) { + \unlink($value); + } + } + }); + } + } +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Response.php b/cacme/vendor/workerman/workerman/Protocols/Http/Response.php new file mode 100644 index 0000000..e423727 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Response.php @@ -0,0 +1,458 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http; + +/** + * Class Response + * @package Workerman\Protocols\Http + */ +class Response +{ + /** + * Header data. + * + * @var array + */ + protected $_header = null; + + /** + * Http status. + * + * @var int + */ + protected $_status = null; + + /** + * Http reason. + * + * @var string + */ + protected $_reason = null; + + /** + * Http version. + * + * @var string + */ + protected $_version = '1.1'; + + /** + * Http body. + * + * @var string + */ + protected $_body = null; + + /** + * Send file info + * + * @var array + */ + public $file = null; + + /** + * Mine type map. + * @var array + */ + protected static $_mimeTypeMap = null; + + /** + * Phrases. + * + * @var array + */ + protected static $_phrases = array( + 100 => 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-status', + 208 => 'Already Reported', + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => 'Switch Proxy', + 307 => 'Temporary Redirect', + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Time-out', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Large', + 415 => 'Unsupported Media Type', + 416 => 'Requested range not satisfiable', + 417 => 'Expectation Failed', + 418 => 'I\'m a teapot', + 422 => 'Unprocessable Entity', + 423 => 'Locked', + 424 => 'Failed Dependency', + 425 => 'Unordered Collection', + 426 => 'Upgrade Required', + 428 => 'Precondition Required', + 429 => 'Too Many Requests', + 431 => 'Request Header Fields Too Large', + 451 => 'Unavailable For Legal Reasons', + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Time-out', + 505 => 'HTTP Version not supported', + 506 => 'Variant Also Negotiates', + 507 => 'Insufficient Storage', + 508 => 'Loop Detected', + 511 => 'Network Authentication Required', + ); + + /** + * Init. + * + * @return void + */ + public static function init() { + static::initMimeTypeMap(); + } + + /** + * Response constructor. + * + * @param int $status + * @param array $headers + * @param string $body + */ + public function __construct( + $status = 200, + $headers = array(), + $body = '' + ) { + $this->_status = $status; + $this->_header = $headers; + $this->_body = (string)$body; + } + + /** + * Set header. + * + * @param string $name + * @param string $value + * @return $this + */ + public function header($name, $value) { + $this->_header[$name] = $value; + return $this; + } + + /** + * Set header. + * + * @param string $name + * @param string $value + * @return Response + */ + public function withHeader($name, $value) { + return $this->header($name, $value); + } + + /** + * Set headers. + * + * @param array $headers + * @return $this + */ + public function withHeaders($headers) { + $this->_header = \array_merge_recursive($this->_header, $headers); + return $this; + } + + /** + * Remove header. + * + * @param string $name + * @return $this + */ + public function withoutHeader($name) { + unset($this->_header[$name]); + return $this; + } + + /** + * Get header. + * + * @param string $name + * @return null|array|string + */ + public function getHeader($name) { + if (!isset($this->_header[$name])) { + return null; + } + return $this->_header[$name]; + } + + /** + * Get headers. + * + * @return array + */ + public function getHeaders() { + return $this->_header; + } + + /** + * Set status. + * + * @param int $code + * @param string|null $reason_phrase + * @return $this + */ + public function withStatus($code, $reason_phrase = null) { + $this->_status = $code; + $this->_reason = $reason_phrase; + return $this; + } + + /** + * Get status code. + * + * @return int + */ + public function getStatusCode() { + return $this->_status; + } + + /** + * Get reason phrase. + * + * @return string + */ + public function getReasonPhrase() { + return $this->_reason; + } + + /** + * Set protocol version. + * + * @param int $version + * @return $this + */ + public function withProtocolVersion($version) { + $this->_version = $version; + return $this; + } + + /** + * Set http body. + * + * @param string $body + * @return $this + */ + public function withBody($body) { + $this->_body = $body; + return $this; + } + + /** + * Get http raw body. + * + * @return string + */ + public function rawBody() { + return $this->_body; + } + + /** + * Send file. + * + * @param string $file + * @param int $offset + * @param int $length + * @return $this + */ + public function withFile($file, $offset = 0, $length = 0) { + if (!\is_file($file)) { + return $this->withStatus(404)->withBody('

404 Not Found

'); + } + $this->file = array('file' => $file, 'offset' => $offset, 'length' => $length); + return $this; + } + + /** + * Set cookie. + * + * @param $name + * @param string $value + * @param int $max_age + * @param string $path + * @param string $domain + * @param bool $secure + * @param bool $http_only + * @param string $same_site + * @return $this + */ + public function cookie($name, $value = '', $max_age = null, $path = '', $domain = '', $secure = false, $http_only = false, $same_site = '') + { + $this->_header['Set-Cookie'][] = $name . '=' . \rawurlencode($value) + . (empty($domain) ? '' : '; Domain=' . $domain) + . ($max_age === null ? '' : '; Max-Age=' . $max_age) + . (empty($path) ? '' : '; Path=' . $path) + . (!$secure ? '' : '; Secure') + . (!$http_only ? '' : '; HttpOnly') + . (empty($same_site) ? '' : '; SameSite=' . $same_site); + return $this; + } + + /** + * Create header for file. + * + * @param array $file_info + * @return string + */ + protected function createHeadForFile($file_info) + { + $file = $file_info['file']; + $reason = $this->_reason ? $this->_reason : static::$_phrases[$this->_status]; + $head = "HTTP/{$this->_version} {$this->_status} $reason\r\n"; + $headers = $this->_header; + if (!isset($headers['Server'])) { + $head .= "Server: workerman\r\n"; + } + foreach ($headers as $name => $value) { + if (\is_array($value)) { + foreach ($value as $item) { + $head .= "$name: $item\r\n"; + } + continue; + } + $head .= "$name: $value\r\n"; + } + + if (!isset($headers['Connection'])) { + $head .= "Connection: keep-alive\r\n"; + } + + $file_info = \pathinfo($file); + $extension = isset($file_info['extension']) ? $file_info['extension'] : ''; + $base_name = isset($file_info['basename']) ? $file_info['basename'] : 'unknown'; + if (!isset($headers['Content-Type'])) { + if (isset(self::$_mimeTypeMap[$extension])) { + $head .= "Content-Type: " . self::$_mimeTypeMap[$extension] . "\r\n"; + } else { + $head .= "Content-Type: application/octet-stream\r\n"; + } + } + + if (!isset($headers['Content-Disposition']) && !isset(self::$_mimeTypeMap[$extension])) { + $head .= "Content-Disposition: attachment; filename=\"$base_name\"\r\n"; + } + + if (!isset($headers['Last-Modified'])) { + if ($mtime = \filemtime($file)) { + $head .= 'Last-Modified: '. \gmdate('D, d M Y H:i:s', $mtime) . ' GMT' . "\r\n"; + } + } + + return "{$head}\r\n"; + } + + /** + * __toString. + * + * @return string + */ + public function __toString() + { + if (isset($this->file)) { + return $this->createHeadForFile($this->file); + } + + $reason = $this->_reason ? $this->_reason : static::$_phrases[$this->_status]; + $body_len = \strlen($this->_body); + if (empty($this->_header)) { + return "HTTP/{$this->_version} {$this->_status} $reason\r\nServer: workerman\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: $body_len\r\nConnection: keep-alive\r\n\r\n{$this->_body}"; + } + + $head = "HTTP/{$this->_version} {$this->_status} $reason\r\n"; + $headers = $this->_header; + if (!isset($headers['Server'])) { + $head .= "Server: workerman\r\n"; + } + foreach ($headers as $name => $value) { + if (\is_array($value)) { + foreach ($value as $item) { + $head .= "$name: $item\r\n"; + } + continue; + } + $head .= "$name: $value\r\n"; + } + + if (!isset($headers['Connection'])) { + $head .= "Connection: keep-alive\r\n"; + } + + if (!isset($headers['Content-Type'])) { + $head .= "Content-Type: text/html;charset=utf-8\r\n"; + } else if ($headers['Content-Type'] === 'text/event-stream') { + return $head . $this->_body; + } + + if (!isset($headers['Transfer-Encoding'])) { + $head .= "Content-Length: $body_len\r\n\r\n"; + } else { + return $body_len ? "$head\r\n" . dechex($body_len) . "\r\n{$this->_body}\r\n" : "$head\r\n"; + } + + // The whole http package + return $head . $this->_body; + } + + /** + * Init mime map. + * + * @return void + */ + public static function initMimeTypeMap() + { + $mime_file = __DIR__ . '/mime.types'; + $items = \file($mime_file, \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES); + foreach ($items as $content) { + if (\preg_match("/\s*(\S+)\s+(\S.+)/", $content, $match)) { + $mime_type = $match[1]; + $extension_var = $match[2]; + $extension_array = \explode(' ', \substr($extension_var, 0, -1)); + foreach ($extension_array as $file_extension) { + static::$_mimeTypeMap[$file_extension] = $mime_type; + } + } + } + } +} +Response::init(); diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/ServerSentEvents.php b/cacme/vendor/workerman/workerman/Protocols/Http/ServerSentEvents.php new file mode 100644 index 0000000..a6e9e0d --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/ServerSentEvents.php @@ -0,0 +1,64 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http; + +/** + * Class ServerSentEvents + * @package Workerman\Protocols\Http + */ +class ServerSentEvents +{ + /** + * Data. + * @var array + */ + protected $_data = null; + + /** + * ServerSentEvents constructor. + * $data for example ['event'=>'ping', 'data' => 'some thing', 'id' => 1000, 'retry' => 5000] + * @param array $data + */ + public function __construct(array $data) + { + $this->_data = $data; + } + + /** + * __toString. + * + * @return string + */ + public function __toString() + { + $buffer = ''; + $data = $this->_data; + if (isset($data[''])) { + $buffer = ": {$data['']}\n"; + } + if (isset($data['event'])) { + $buffer .= "event: {$data['event']}\n"; + } + if (isset($data['id'])) { + $buffer .= "id: {$data['id']}\n"; + } + if (isset($data['retry'])) { + $buffer .= "retry: {$data['retry']}\n"; + } + if (isset($data['data'])) { + $buffer .= 'data: ' . str_replace("\n", "\ndata: ", $data['data']) . "\n"; + } + return $buffer . "\n"; + } +} \ No newline at end of file diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Session.php b/cacme/vendor/workerman/workerman/Protocols/Http/Session.php new file mode 100644 index 0000000..a0c2417 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Session.php @@ -0,0 +1,461 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Workerman\Protocols\Http; + +use Workerman\Protocols\Http\Session\SessionHandlerInterface; + +/** + * Class Session + * @package Workerman\Protocols\Http + */ +class Session +{ + /** + * Session andler class which implements SessionHandlerInterface. + * + * @var string + */ + protected static $_handlerClass = 'Workerman\Protocols\Http\Session\FileSessionHandler'; + + /** + * Parameters of __constructor for session handler class. + * + * @var null + */ + protected static $_handlerConfig = null; + + /** + * Session name. + * + * @var string + */ + public static $name = 'PHPSID'; + + /** + * Auto update timestamp. + * + * @var bool + */ + public static $autoUpdateTimestamp = false; + + /** + * Session lifetime. + * + * @var int + */ + public static $lifetime = 1440; + + /** + * Cookie lifetime. + * + * @var int + */ + public static $cookieLifetime = 1440; + + /** + * Session cookie path. + * + * @var string + */ + public static $cookiePath = '/'; + + /** + * Session cookie domain. + * + * @var string + */ + public static $domain = ''; + + /** + * HTTPS only cookies. + * + * @var bool + */ + public static $secure = false; + + /** + * HTTP access only. + * + * @var bool + */ + public static $httpOnly = true; + + /** + * Same-site cookies. + * + * @var string + */ + public static $sameSite = ''; + + /** + * Gc probability. + * + * @var int[] + */ + public static $gcProbability = [1, 1000]; + + /** + * Session handler instance. + * + * @var SessionHandlerInterface + */ + protected static $_handler = null; + + /** + * Session data. + * + * @var array + */ + protected $_data = []; + + /** + * Session changed and need to save. + * + * @var bool + */ + protected $_needSave = false; + + /** + * Session id. + * + * @var null + */ + protected $_sessionId = null; + + /** + * Is safe. + * + * @var bool + */ + protected $_isSafe = true; + + /** + * Session constructor. + * + * @param string $session_id + */ + public function __construct($session_id) + { + static::checkSessionId($session_id); + if (static::$_handler === null) { + static::initHandler(); + } + $this->_sessionId = $session_id; + if ($data = static::$_handler->read($session_id)) { + $this->_data = \unserialize($data); + } + } + + /** + * Get session id. + * + * @return string + */ + public function getId() + { + return $this->_sessionId; + } + + /** + * Get session. + * + * @param string $name + * @param mixed|null $default + * @return mixed|null + */ + public function get($name, $default = null) + { + return isset($this->_data[$name]) ? $this->_data[$name] : $default; + } + + /** + * Store data in the session. + * + * @param string $name + * @param mixed $value + */ + public function set($name, $value) + { + $this->_data[$name] = $value; + $this->_needSave = true; + } + + /** + * Delete an item from the session. + * + * @param string $name + */ + public function delete($name) + { + unset($this->_data[$name]); + $this->_needSave = true; + } + + /** + * Retrieve and delete an item from the session. + * + * @param string $name + * @param mixed|null $default + * @return mixed|null + */ + public function pull($name, $default = null) + { + $value = $this->get($name, $default); + $this->delete($name); + return $value; + } + + /** + * Store data in the session. + * + * @param string|array $key + * @param mixed|null $value + */ + public function put($key, $value = null) + { + if (!\is_array($key)) { + $this->set($key, $value); + return; + } + + foreach ($key as $k => $v) { + $this->_data[$k] = $v; + } + $this->_needSave = true; + } + + /** + * Remove a piece of data from the session. + * + * @param string $name + */ + public function forget($name) + { + if (\is_scalar($name)) { + $this->delete($name); + return; + } + if (\is_array($name)) { + foreach ($name as $key) { + unset($this->_data[$key]); + } + } + $this->_needSave = true; + } + + /** + * Retrieve all the data in the session. + * + * @return array + */ + public function all() + { + return $this->_data; + } + + /** + * Remove all data from the session. + * + * @return void + */ + public function flush() + { + $this->_needSave = true; + $this->_data = []; + } + + /** + * Determining If An Item Exists In The Session. + * + * @param string $name + * @return bool + */ + public function has($name) + { + return isset($this->_data[$name]); + } + + /** + * To determine if an item is present in the session, even if its value is null. + * + * @param string $name + * @return bool + */ + public function exists($name) + { + return \array_key_exists($name, $this->_data); + } + + /** + * Save session to store. + * + * @return void + */ + public function save() + { + if ($this->_needSave) { + if (empty($this->_data)) { + static::$_handler->destroy($this->_sessionId); + } else { + static::$_handler->write($this->_sessionId, \serialize($this->_data)); + } + } elseif (static::$autoUpdateTimestamp) { + static::refresh(); + } + $this->_needSave = false; + } + + /** + * Refresh session expire time. + * + * @return bool + */ + public function refresh() + { + static::$_handler->updateTimestamp($this->getId()); + } + + /** + * Init. + * + * @return void + */ + public static function init() + { + if (($gc_probability = (int)\ini_get('session.gc_probability')) && ($gc_divisor = (int)\ini_get('session.gc_divisor'))) { + static::$gcProbability = [$gc_probability, $gc_divisor]; + } + + if ($gc_max_life_time = \ini_get('session.gc_maxlifetime')) { + self::$lifetime = (int)$gc_max_life_time; + } + + $session_cookie_params = \session_get_cookie_params(); + static::$cookieLifetime = $session_cookie_params['lifetime']; + static::$cookiePath = $session_cookie_params['path']; + static::$domain = $session_cookie_params['domain']; + static::$secure = $session_cookie_params['secure']; + static::$httpOnly = $session_cookie_params['httponly']; + } + + /** + * Set session handler class. + * + * @param mixed|null $class_name + * @param mixed|null $config + * @return string + */ + public static function handlerClass($class_name = null, $config = null) + { + if ($class_name) { + static::$_handlerClass = $class_name; + } + if ($config) { + static::$_handlerConfig = $config; + } + return static::$_handlerClass; + } + + /** + * Get cookie params. + * + * @return array + */ + public static function getCookieParams() + { + return [ + 'lifetime' => static::$cookieLifetime, + 'path' => static::$cookiePath, + 'domain' => static::$domain, + 'secure' => static::$secure, + 'httponly' => static::$httpOnly, + 'samesite' => static::$sameSite, + ]; + } + + /** + * Init handler. + * + * @return void + */ + protected static function initHandler() + { + if (static::$_handlerConfig === null) { + static::$_handler = new static::$_handlerClass(); + } else { + static::$_handler = new static::$_handlerClass(static::$_handlerConfig); + } + } + + /** + * GC sessions. + * + * @return void + */ + public function gc() + { + static::$_handler->gc(static::$lifetime); + } + + /** + * __wakeup. + * + * @return void + */ + public function __wakeup() + { + $this->_isSafe = false; + } + + /** + * __destruct. + * + * @return void + */ + public function __destruct() + { + if (!$this->_isSafe) { + return; + } + $this->save(); + if (\random_int(1, static::$gcProbability[1]) <= static::$gcProbability[0]) { + $this->gc(); + } + } + + /** + * Check session id. + * + * @param string $session_id + */ + protected static function checkSessionId($session_id) + { + if (!\preg_match('/^[a-zA-Z0-9"]+$/', $session_id)) { + throw new SessionException("session_id $session_id is invalid"); + } + } +} + +/** + * Class SessionException + * @package Workerman\Protocols\Http + */ +class SessionException extends \RuntimeException +{ + +} + +// Init session. +Session::init(); diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Session/FileSessionHandler.php b/cacme/vendor/workerman/workerman/Protocols/Http/Session/FileSessionHandler.php new file mode 100644 index 0000000..a7cefbd --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Session/FileSessionHandler.php @@ -0,0 +1,183 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http\Session; + +use Workerman\Protocols\Http\Session; + +/** + * Class FileSessionHandler + * @package Workerman\Protocols\Http\Session + */ +class FileSessionHandler implements SessionHandlerInterface +{ + /** + * Session save path. + * + * @var string + */ + protected static $_sessionSavePath = null; + + /** + * Session file prefix. + * + * @var string + */ + protected static $_sessionFilePrefix = 'session_'; + + /** + * Init. + */ + public static function init() { + $save_path = @\session_save_path(); + if (!$save_path || \strpos($save_path, 'tcp://') === 0) { + $save_path = \sys_get_temp_dir(); + } + static::sessionSavePath($save_path); + } + + /** + * FileSessionHandler constructor. + * @param array $config + */ + public function __construct($config = array()) { + if (isset($config['save_path'])) { + static::sessionSavePath($config['save_path']); + } + } + + /** + * {@inheritdoc} + */ + public function open($save_path, $name) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function read($session_id) + { + $session_file = static::sessionFile($session_id); + \clearstatcache(); + if (\is_file($session_file)) { + if (\time() - \filemtime($session_file) > Session::$lifetime) { + \unlink($session_file); + return ''; + } + $data = \file_get_contents($session_file); + return $data ? $data : ''; + } + return ''; + } + + /** + * {@inheritdoc} + */ + public function write($session_id, $session_data) + { + $temp_file = static::$_sessionSavePath . uniqid(bin2hex(random_bytes(8)), true); + if (!\file_put_contents($temp_file, $session_data)) { + return false; + } + return \rename($temp_file, static::sessionFile($session_id)); + } + + /** + * Update sesstion modify time. + * + * @see https://www.php.net/manual/en/class.sessionupdatetimestamphandlerinterface.php + * @see https://www.php.net/manual/zh/function.touch.php + * + * @param string $id Session id. + * @param string $data Session Data. + * + * @return bool + */ + public function updateTimestamp($id, $data = "") + { + $session_file = static::sessionFile($id); + if (!file_exists($session_file)) { + return false; + } + // set file modify time to current time + $set_modify_time = \touch($session_file); + // clear file stat cache + \clearstatcache(); + return $set_modify_time; + } + + /** + * {@inheritdoc} + */ + public function close() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function destroy($session_id) + { + $session_file = static::sessionFile($session_id); + if (\is_file($session_file)) { + \unlink($session_file); + } + return true; + } + + /** + * {@inheritdoc} + */ + public function gc($maxlifetime) { + $time_now = \time(); + foreach (\glob(static::$_sessionSavePath . static::$_sessionFilePrefix . '*') as $file) { + if(\is_file($file) && $time_now - \filemtime($file) > $maxlifetime) { + \unlink($file); + } + } + } + + /** + * Get session file path. + * + * @param string $session_id + * @return string + */ + protected static function sessionFile($session_id) { + return static::$_sessionSavePath.static::$_sessionFilePrefix.$session_id; + } + + /** + * Get or set session file path. + * + * @param string $path + * @return string + */ + public static function sessionSavePath($path) { + if ($path) { + if ($path[\strlen($path)-1] !== DIRECTORY_SEPARATOR) { + $path .= DIRECTORY_SEPARATOR; + } + static::$_sessionSavePath = $path; + if (!\is_dir($path)) { + \mkdir($path, 0777, true); + } + } + return $path; + } +} + +FileSessionHandler::init(); \ No newline at end of file diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisClusterSessionHandler.php b/cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisClusterSessionHandler.php new file mode 100644 index 0000000..281759a --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisClusterSessionHandler.php @@ -0,0 +1,46 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Workerman\Protocols\Http\Session; + +use Workerman\Protocols\Http\Session; + +class RedisClusterSessionHandler extends RedisSessionHandler +{ + public function __construct($config) + { + $timeout = isset($config['timeout']) ? $config['timeout'] : 2; + $read_timeout = isset($config['read_timeout']) ? $config['read_timeout'] : $timeout; + $persistent = isset($config['persistent']) ? $config['persistent'] : false; + $auth = isset($config['auth']) ? $config['auth'] : ''; + if ($auth) { + $this->_redis = new \RedisCluster(null, $config['host'], $timeout, $read_timeout, $persistent, $auth); + } else { + $this->_redis = new \RedisCluster(null, $config['host'], $timeout, $read_timeout, $persistent); + } + if (empty($config['prefix'])) { + $config['prefix'] = 'redis_session_'; + } + $this->_redis->setOption(\Redis::OPT_PREFIX, $config['prefix']); + } + + /** + * {@inheritdoc} + */ + public function read($session_id) + { + return $this->_redis->get($session_id); + } + +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisSessionHandler.php b/cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisSessionHandler.php new file mode 100644 index 0000000..e1b5bd5 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Session/RedisSessionHandler.php @@ -0,0 +1,154 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http\Session; + +use Workerman\Protocols\Http\Session; +use Workerman\Timer; +use RedisException; + +/** + * Class RedisSessionHandler + * @package Workerman\Protocols\Http\Session + */ +class RedisSessionHandler implements SessionHandlerInterface +{ + + /** + * @var \Redis + */ + protected $_redis; + + /** + * @var array + */ + protected $_config; + + /** + * RedisSessionHandler constructor. + * @param array $config = [ + * 'host' => '127.0.0.1', + * 'port' => 6379, + * 'timeout' => 2, + * 'auth' => '******', + * 'database' => 2, + * 'prefix' => 'redis_session_', + * 'ping' => 55, + * ] + */ + public function __construct($config) + { + if (false === extension_loaded('redis')) { + throw new \RuntimeException('Please install redis extension.'); + } + + if (!isset($config['timeout'])) { + $config['timeout'] = 2; + } + + $this->_config = $config; + + $this->connect(); + + Timer::add(!empty($config['ping']) ? $config['ping'] : 55, function () { + $this->_redis->get('ping'); + }); + } + + public function connect() + { + $config = $this->_config; + + $this->_redis = new \Redis(); + if (false === $this->_redis->connect($config['host'], $config['port'], $config['timeout'])) { + throw new \RuntimeException("Redis connect {$config['host']}:{$config['port']} fail."); + } + if (!empty($config['auth'])) { + $this->_redis->auth($config['auth']); + } + if (!empty($config['database'])) { + $this->_redis->select($config['database']); + } + if (empty($config['prefix'])) { + $config['prefix'] = 'redis_session_'; + } + $this->_redis->setOption(\Redis::OPT_PREFIX, $config['prefix']); + } + + /** + * {@inheritdoc} + */ + public function open($save_path, $name) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function read($session_id) + { + try { + return $this->_redis->get($session_id); + } catch (RedisException $e) { + $msg = strtolower($e->getMessage()); + if ($msg === 'connection lost' || strpos($msg, 'went away')) { + $this->connect(); + return $this->_redis->get($session_id); + } + throw $e; + } + + } + + /** + * {@inheritdoc} + */ + public function write($session_id, $session_data) + { + return true === $this->_redis->setex($session_id, Session::$lifetime, $session_data); + } + + /** + * {@inheritdoc} + */ + public function updateTimestamp($id, $data = "") + { + return true === $this->_redis->expire($id, Session::$lifetime); + } + + /** + * {@inheritdoc} + */ + public function destroy($session_id) + { + $this->_redis->del($session_id); + return true; + } + + /** + * {@inheritdoc} + */ + public function close() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function gc($maxlifetime) + { + return true; + } +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/Session/SessionHandlerInterface.php b/cacme/vendor/workerman/workerman/Protocols/Http/Session/SessionHandlerInterface.php new file mode 100644 index 0000000..23a47f2 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/Session/SessionHandlerInterface.php @@ -0,0 +1,114 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols\Http\Session; + +interface SessionHandlerInterface +{ + /** + * Close the session + * @link http://php.net/manual/en/sessionhandlerinterface.close.php + * @return bool

+ * The return value (usually TRUE on success, FALSE on failure). + * Note this value is returned internally to PHP for processing. + *

+ * @since 5.4.0 + */ + public function close(); + + /** + * Destroy a session + * @link http://php.net/manual/en/sessionhandlerinterface.destroy.php + * @param string $session_id The session ID being destroyed. + * @return bool

+ * The return value (usually TRUE on success, FALSE on failure). + * Note this value is returned internally to PHP for processing. + *

+ * @since 5.4.0 + */ + public function destroy($session_id); + + /** + * Cleanup old sessions + * @link http://php.net/manual/en/sessionhandlerinterface.gc.php + * @param int $maxlifetime

+ * Sessions that have not updated for + * the last maxlifetime seconds will be removed. + *

+ * @return bool

+ * The return value (usually TRUE on success, FALSE on failure). + * Note this value is returned internally to PHP for processing. + *

+ * @since 5.4.0 + */ + public function gc($maxlifetime); + + /** + * Initialize session + * @link http://php.net/manual/en/sessionhandlerinterface.open.php + * @param string $save_path The path where to store/retrieve the session. + * @param string $name The session name. + * @return bool

+ * The return value (usually TRUE on success, FALSE on failure). + * Note this value is returned internally to PHP for processing. + *

+ * @since 5.4.0 + */ + public function open($save_path, $name); + + + /** + * Read session data + * @link http://php.net/manual/en/sessionhandlerinterface.read.php + * @param string $session_id The session id to read data for. + * @return string

+ * Returns an encoded string of the read data. + * If nothing was read, it must return an empty string. + * Note this value is returned internally to PHP for processing. + *

+ * @since 5.4.0 + */ + public function read($session_id); + + /** + * Write session data + * @link http://php.net/manual/en/sessionhandlerinterface.write.php + * @param string $session_id The session id. + * @param string $session_data

+ * The encoded session data. This data is the + * result of the PHP internally encoding + * the $_SESSION superglobal to a serialized + * string and passing it as this parameter. + * Please note sessions use an alternative serialization method. + *

+ * @return bool

+ * The return value (usually TRUE on success, FALSE on failure). + * Note this value is returned internally to PHP for processing. + *

+ * @since 5.4.0 + */ + public function write($session_id, $session_data); + + /** + * Update sesstion modify time. + * + * @see https://www.php.net/manual/en/class.sessionupdatetimestamphandlerinterface.php + * + * @param string $id Session id. + * @param string $data Session Data. + * + * @return bool + */ + public function updateTimestamp($id, $data = ""); + +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Http/mime.types b/cacme/vendor/workerman/workerman/Protocols/Http/mime.types new file mode 100644 index 0000000..e6ccf0a --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Http/mime.types @@ -0,0 +1,90 @@ + +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + image/svg+xml svg svgz; + image/webp webp; + + application/font-woff woff; + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.wap.wmlc wmlc; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; + application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; + font/ttf ttf; +} diff --git a/cacme/vendor/workerman/workerman/Protocols/ProtocolInterface.php b/cacme/vendor/workerman/workerman/Protocols/ProtocolInterface.php new file mode 100644 index 0000000..4fea87d --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/ProtocolInterface.php @@ -0,0 +1,52 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols; + +use Workerman\Connection\ConnectionInterface; + +/** + * Protocol interface + */ +interface ProtocolInterface +{ + /** + * Check the integrity of the package. + * Please return the length of package. + * If length is unknow please return 0 that mean wating more data. + * If the package has something wrong please return false the connection will be closed. + * + * @param string $recv_buffer + * @param ConnectionInterface $connection + * @return int|false + */ + public static function input($recv_buffer, ConnectionInterface $connection); + + /** + * Decode package and emit onMessage($message) callback, $message is the result that decode returned. + * + * @param string $recv_buffer + * @param ConnectionInterface $connection + * @return mixed + */ + public static function decode($recv_buffer, ConnectionInterface $connection); + + /** + * Encode package brefore sending to client. + * + * @param mixed $data + * @param ConnectionInterface $connection + * @return string + */ + public static function encode($data, ConnectionInterface $connection); +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Text.php b/cacme/vendor/workerman/workerman/Protocols/Text.php new file mode 100644 index 0000000..407ea2d --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Text.php @@ -0,0 +1,70 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Protocols; + +use Workerman\Connection\ConnectionInterface; + +/** + * Text Protocol. + */ +class Text +{ + /** + * Check the integrity of the package. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return int + */ + public static function input($buffer, ConnectionInterface $connection) + { + // Judge whether the package length exceeds the limit. + if (isset($connection->maxPackageSize) && \strlen($buffer) >= $connection->maxPackageSize) { + $connection->close(); + return 0; + } + // Find the position of "\n". + $pos = \strpos($buffer, "\n"); + // No "\n", packet length is unknown, continue to wait for the data so return 0. + if ($pos === false) { + return 0; + } + // Return the current package length. + return $pos + 1; + } + + /** + * Encode. + * + * @param string $buffer + * @return string + */ + public static function encode($buffer) + { + // Add "\n" + return $buffer . "\n"; + } + + /** + * Decode. + * + * @param string $buffer + * @return string + */ + public static function decode($buffer) + { + // Remove "\n" + return \rtrim($buffer, "\r\n"); + } +} \ No newline at end of file diff --git a/cacme/vendor/workerman/workerman/Protocols/Websocket.php b/cacme/vendor/workerman/workerman/Protocols/Websocket.php new file mode 100644 index 0000000..0f94de6 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Websocket.php @@ -0,0 +1,564 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Workerman\Protocols; + +use Workerman\Connection\ConnectionInterface; +use Workerman\Connection\TcpConnection; +use Workerman\Protocols\Http\Request; +use Workerman\Worker; + +/** + * WebSocket protocol. + */ +class Websocket implements \Workerman\Protocols\ProtocolInterface +{ + /** + * Websocket blob type. + * + * @var string + */ + const BINARY_TYPE_BLOB = "\x81"; + + /** + * Websocket blob type. + * + * @var string + */ + const BINARY_TYPE_BLOB_DEFLATE = "\xc1"; + + /** + * Websocket arraybuffer type. + * + * @var string + */ + const BINARY_TYPE_ARRAYBUFFER = "\x82"; + + /** + * Websocket arraybuffer type. + * + * @var string + */ + const BINARY_TYPE_ARRAYBUFFER_DEFLATE = "\xc2"; + + /** + * Check the integrity of the package. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return int + */ + public static function input($buffer, ConnectionInterface $connection) + { + // Receive length. + $recv_len = \strlen($buffer); + // We need more data. + if ($recv_len < 6) { + return 0; + } + + // Has not yet completed the handshake. + if (empty($connection->context->websocketHandshake)) { + return static::dealHandshake($buffer, $connection); + } + + // Buffer websocket frame data. + if ($connection->context->websocketCurrentFrameLength) { + // We need more frame data. + if ($connection->context->websocketCurrentFrameLength > $recv_len) { + // Return 0, because it is not clear the full packet length, waiting for the frame of fin=1. + return 0; + } + } else { + $first_byte = \ord($buffer[0]); + $second_byte = \ord($buffer[1]); + $data_len = $second_byte & 127; + $is_fin_frame = $first_byte >> 7; + $masked = $second_byte >> 7; + + if (!$masked) { + Worker::safeEcho("frame not masked so close the connection\n"); + $connection->close(); + return 0; + } + + $opcode = $first_byte & 0xf; + switch ($opcode) { + case 0x0: + break; + // Blob type. + case 0x1: + break; + // Arraybuffer type. + case 0x2: + break; + // Close package. + case 0x8: + // Try to emit onWebSocketClose callback. + $close_cb = $connection->onWebSocketClose ?? $connection->worker->onWebSocketClose ?? false; + if ($close_cb) { + try { + $close_cb($connection); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } // Close connection. + else { + $connection->close("\x88\x02\x03\xe8", true); + } + return 0; + // Ping package. + case 0x9: + break; + // Pong package. + case 0xa: + break; + // Wrong opcode. + default : + Worker::safeEcho("error opcode $opcode and close websocket connection. Buffer:" . bin2hex($buffer) . "\n"); + $connection->close(); + return 0; + } + + // Calculate packet length. + $head_len = 6; + if ($data_len === 126) { + $head_len = 8; + if ($head_len > $recv_len) { + return 0; + } + $pack = \unpack('nn/ntotal_len', $buffer); + $data_len = $pack['total_len']; + } else { + if ($data_len === 127) { + $head_len = 14; + if ($head_len > $recv_len) { + return 0; + } + $arr = \unpack('n/N2c', $buffer); + $data_len = $arr['c1'] * 4294967296 + $arr['c2']; + } + } + $current_frame_length = $head_len + $data_len; + + $total_package_size = \strlen($connection->context->websocketDataBuffer) + $current_frame_length; + if ($total_package_size > $connection->maxPackageSize) { + Worker::safeEcho("error package. package_length=$total_package_size\n"); + $connection->close(); + return 0; + } + + if ($is_fin_frame) { + if ($opcode === 0x9) { + if ($recv_len >= $current_frame_length) { + $ping_data = static::decode(\substr($buffer, 0, $current_frame_length), $connection); + $connection->consumeRecvBuffer($current_frame_length); + $tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB; + $connection->websocketType = "\x8a"; + $ping_cb = $connection->onWebSocketPing ?? $connection->worker->onWebSocketPing ?? false; + if ($ping_cb) { + try { + $ping_cb($connection, $ping_data); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } else { + $connection->send($ping_data); + } + $connection->websocketType = $tmp_connection_type; + if ($recv_len > $current_frame_length) { + return static::input(\substr($buffer, $current_frame_length), $connection); + } + } + return 0; + } else if ($opcode === 0xa) { + if ($recv_len >= $current_frame_length) { + $pong_data = static::decode(\substr($buffer, 0, $current_frame_length), $connection); + $connection->consumeRecvBuffer($current_frame_length); + $tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB; + $connection->websocketType = "\x8a"; + // Try to emit onWebSocketPong callback. + $pong_cb = $connection->onWebSocketPong ?? $connection->worker->onWebSocketPong ?? false; + if ($pong_cb) { + try { + $pong_cb($connection, $pong_data); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + $connection->websocketType = $tmp_connection_type; + if ($recv_len > $current_frame_length) { + return static::input(\substr($buffer, $current_frame_length), $connection); + } + } + return 0; + } + return $current_frame_length; + } else { + $connection->context->websocketCurrentFrameLength = $current_frame_length; + } + } + + // Received just a frame length data. + if ($connection->context->websocketCurrentFrameLength === $recv_len) { + static::decode($buffer, $connection); + $connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength); + $connection->context->websocketCurrentFrameLength = 0; + return 0; + } // The length of the received data is greater than the length of a frame. + elseif ($connection->context->websocketCurrentFrameLength < $recv_len) { + static::decode(\substr($buffer, 0, $connection->context->websocketCurrentFrameLength), $connection); + $connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength); + $current_frame_length = $connection->context->websocketCurrentFrameLength; + $connection->context->websocketCurrentFrameLength = 0; + // Continue to read next frame. + return static::input(\substr($buffer, $current_frame_length), $connection); + } // The length of the received data is less than the length of a frame. + else { + return 0; + } + } + + /** + * Websocket encode. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return string + */ + public static function encode($buffer, ConnectionInterface $connection) + { + if (!is_scalar($buffer)) { + throw new \Exception("You can't send(" . \gettype($buffer) . ") to client, you need to convert it to a string. "); + } + + if (empty($connection->websocketType)) { + $connection->websocketType = static::BINARY_TYPE_BLOB; + } + + // permessage-deflate + if (\ord($connection->websocketType) & 64) { + $buffer = static::deflate($connection, $buffer); + } + + $first_byte = $connection->websocketType; + $len = \strlen($buffer); + + if ($len <= 125) { + $encode_buffer = $first_byte . \chr($len) . $buffer; + } else { + if ($len <= 65535) { + $encode_buffer = $first_byte . \chr(126) . \pack("n", $len) . $buffer; + } else { + $encode_buffer = $first_byte . \chr(127) . \pack("xxxxN", $len) . $buffer; + } + } + + // Handshake not completed so temporary buffer websocket data waiting for send. + if (empty($connection->context->websocketHandshake)) { + if (empty($connection->context->tmpWebsocketData)) { + $connection->context->tmpWebsocketData = ''; + } + // If buffer has already full then discard the current package. + if (\strlen($connection->context->tmpWebsocketData) > $connection->maxSendBufferSize) { + if ($connection->onError) { + try { + ($connection->onError)($connection, WORKERMAN_SEND_FAIL, 'send buffer full and drop package'); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + return ''; + } + $connection->context->tmpWebsocketData .= $encode_buffer; + // Check buffer is full. + if ($connection->maxSendBufferSize <= \strlen($connection->context->tmpWebsocketData)) { + if ($connection->onBufferFull) { + try { + ($connection->onBufferFull)($connection); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + } + // Return empty string. + return ''; + } + + return $encode_buffer; + } + + /** + * Websocket decode. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return string + */ + public static function decode($buffer, ConnectionInterface $connection) + { + $first_byte = \ord($buffer[0]); + $second_byte = \ord($buffer[1]); + $len = $second_byte & 127; + $is_fin_frame = $first_byte >> 7; + $rsv1 = 64 === ($first_byte & 64); + + if ($len === 126) { + $masks = \substr($buffer, 4, 4); + $data = \substr($buffer, 8); + } else { + if ($len === 127) { + $masks = \substr($buffer, 10, 4); + $data = \substr($buffer, 14); + } else { + $masks = \substr($buffer, 2, 4); + $data = \substr($buffer, 6); + } + } + $dataLength = \strlen($data); + $masks = \str_repeat($masks, \floor($dataLength / 4)) . \substr($masks, 0, $dataLength % 4); + $decoded = $data ^ $masks; + if ($connection->context->websocketCurrentFrameLength) { + $connection->context->websocketDataBuffer .= $decoded; + if ($rsv1) { + return static::inflate($connection, $connection->context->websocketDataBuffer, $is_fin_frame); + } + return $connection->context->websocketDataBuffer; + } else { + if ($connection->context->websocketDataBuffer !== '') { + $decoded = $connection->context->websocketDataBuffer . $decoded; + $connection->context->websocketDataBuffer = ''; + } + if ($rsv1) { + return static::inflate($connection, $decoded, $is_fin_frame); + } + return $decoded; + } + } + + /** + * Inflate. + * + * @param $connection + * @param $buffer + * @param $is_fin_frame + * @return false|string + */ + protected static function inflate($connection, $buffer, $is_fin_frame) + { + if (!isset($connection->context->inflator)) { + $connection->context->inflator = \inflate_init( + \ZLIB_ENCODING_RAW, + [ + 'level' => -1, + 'memory' => 8, + 'window' => 9, + 'strategy' => \ZLIB_DEFAULT_STRATEGY + ] + ); + } + if ($is_fin_frame) { + $buffer .= "\x00\x00\xff\xff"; + } + return \inflate_add($connection->context->inflator, $buffer); + } + + /** + * Deflate. + * + * @param $connection + * @param $buffer + * @return false|string + */ + protected static function deflate($connection, $buffer) + { + if (!isset($connection->context->deflator)) { + $connection->context->deflator = \deflate_init( + \ZLIB_ENCODING_RAW, + [ + 'level' => -1, + 'memory' => 8, + 'window' => 9, + 'strategy' => \ZLIB_DEFAULT_STRATEGY + ] + ); + } + return \substr(\deflate_add($connection->context->deflator, $buffer), 0, -4); + } + + /** + * Websocket handshake. + * + * @param string $buffer + * @param TcpConnection $connection + * @return int + */ + public static function dealHandshake($buffer, $connection) + { + // HTTP protocol. + if (0 === \strpos($buffer, 'GET')) { + // Find \r\n\r\n. + $header_end_pos = \strpos($buffer, "\r\n\r\n"); + if (!$header_end_pos) { + return 0; + } + $header_length = $header_end_pos + 4; + + // Get Sec-WebSocket-Key. + $Sec_WebSocket_Key = ''; + if (\preg_match("/Sec-WebSocket-Key: *(.*?)\r\n/i", $buffer, $match)) { + $Sec_WebSocket_Key = $match[1]; + } else { + $connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/" . Worker::VERSION . "\r\n\r\n

WebSocket


workerman/" . Worker::VERSION . "
", + true); + return 0; + } + // Calculation websocket key. + $new_key = \base64_encode(\sha1($Sec_WebSocket_Key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true)); + // Handshake response data. + $handshake_message = "HTTP/1.1 101 Switching Protocols\r\n" + . "Upgrade: websocket\r\n" + . "Sec-WebSocket-Version: 13\r\n" + . "Connection: Upgrade\r\n" + . "Sec-WebSocket-Accept: " . $new_key . "\r\n"; + + // Websocket data buffer. + $connection->context->websocketDataBuffer = ''; + // Current websocket frame length. + $connection->context->websocketCurrentFrameLength = 0; + // Current websocket frame data. + $connection->context->websocketCurrentFrameBuffer = ''; + // Consume handshake data. + $connection->consumeRecvBuffer($header_length); + + // Try to emit onWebSocketConnect callback. + $on_websocket_connect = $connection->onWebSocketConnect ?? $connection->worker->onWebSocketConnect ?? false; + if ($on_websocket_connect) { + static::parseHttpHeader($buffer); + try { + \call_user_func($on_websocket_connect, $connection, $buffer); + } catch (\Exception $e) { + Worker::stopAll(250, $e); + } catch (\Error $e) { + Worker::stopAll(250, $e); + } + if (!empty($_SESSION) && \class_exists('\GatewayWorker\Lib\Context')) { + $connection->session = \GatewayWorker\Lib\Context::sessionEncode($_SESSION); + } + $_GET = $_SERVER = $_SESSION = $_COOKIE = array(); + } + + // blob or arraybuffer + if (empty($connection->websocketType)) { + $connection->websocketType = static::BINARY_TYPE_BLOB; + } + + $has_server_header = false; + + if (isset($connection->headers)) { + if (\is_array($connection->headers)) { + foreach ($connection->headers as $header) { + if (\stripos($header, 'Server:') === 0) { + $has_server_header = true; + } + $handshake_message .= "$header\r\n"; + } + } else { + if (\stripos($connection->headers, 'Server:') !== false) { + $has_server_header = true; + } + $handshake_message .= "$connection->headers\r\n"; + } + } + if (!$has_server_header) { + $handshake_message .= "Server: workerman/" . Worker::VERSION . "\r\n"; + } + $handshake_message .= "\r\n"; + // Send handshake response. + $connection->send($handshake_message, true); + // Mark handshake complete.. + $connection->context->websocketHandshake = true; + + // There are data waiting to be sent. + if (!empty($connection->context->tmpWebsocketData)) { + $connection->send($connection->context->tmpWebsocketData, true); + $connection->context->tmpWebsocketData = ''; + } + if (\strlen($buffer) > $header_length) { + return static::input(\substr($buffer, $header_length), $connection); + } + return 0; + } + // Bad websocket handshake request. + $connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/" . Worker::VERSION . "\r\n\r\n

WebSocket


workerman/" . Worker::VERSION . "
", + true); + return 0; + } + + /** + * Parse http header. + * + * @param string $buffer + * @return void + */ + protected static function parseHttpHeader($buffer) + { + // Parse headers. + list($http_header, ) = \explode("\r\n\r\n", $buffer, 2); + $header_data = \explode("\r\n", $http_header); + + if ($_SERVER) { + $_SERVER = array(); + } + + list($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL']) = \explode(' ', + $header_data[0]); + + unset($header_data[0]); + foreach ($header_data as $content) { + // \r\n\r\n + if (empty($content)) { + continue; + } + list($key, $value) = \explode(':', $content, 2); + $key = \str_replace('-', '_', \strtoupper($key)); + $value = \trim($value); + $_SERVER['HTTP_' . $key] = $value; + switch ($key) { + // HTTP_HOST + case 'HOST': + $tmp = \explode(':', $value); + $_SERVER['SERVER_NAME'] = $tmp[0]; + if (isset($tmp[1])) { + $_SERVER['SERVER_PORT'] = $tmp[1]; + } + break; + // cookie + case 'COOKIE': + \parse_str(\str_replace('; ', '&', $_SERVER['HTTP_COOKIE']), $_COOKIE); + break; + } + } + + // QUERY_STRING + $_SERVER['QUERY_STRING'] = \parse_url($_SERVER['REQUEST_URI'], \PHP_URL_QUERY); + if ($_SERVER['QUERY_STRING']) { + // $GET + \parse_str($_SERVER['QUERY_STRING'], $_GET); + } else { + $_SERVER['QUERY_STRING'] = ''; + } + } + +} diff --git a/cacme/vendor/workerman/workerman/Protocols/Ws.php b/cacme/vendor/workerman/workerman/Protocols/Ws.php new file mode 100644 index 0000000..3db887e --- /dev/null +++ b/cacme/vendor/workerman/workerman/Protocols/Ws.php @@ -0,0 +1,432 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace Workerman\Protocols; + +use Workerman\Worker; +use Workerman\Timer; +use Workerman\Connection\TcpConnection; +use Workerman\Connection\ConnectionInterface; + +/** + * Websocket protocol for client. + */ +class Ws +{ + /** + * Websocket blob type. + * + * @var string + */ + const BINARY_TYPE_BLOB = "\x81"; + + /** + * Websocket arraybuffer type. + * + * @var string + */ + const BINARY_TYPE_ARRAYBUFFER = "\x82"; + + /** + * Check the integrity of the package. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return int + */ + public static function input($buffer, ConnectionInterface $connection) + { + if (empty($connection->context->handshakeStep)) { + Worker::safeEcho("recv data before handshake. Buffer:" . \bin2hex($buffer) . "\n"); + return false; + } + // Recv handshake response + if ($connection->context->handshakeStep === 1) { + return self::dealHandshake($buffer, $connection); + } + $recvLen = \strlen($buffer); + if ($recvLen < 2) { + return 0; + } + // Buffer websocket frame data. + if ($connection->context->websocketCurrentFrameLength) { + // We need more frame data. + if ($connection->context->websocketCurrentFrameLength > $recvLen) { + // Return 0, because it is not clear the full packet length, waiting for the frame of fin=1. + return 0; + } + } else { + + $firstbyte = \ord($buffer[0]); + $secondbyte = \ord($buffer[1]); + $dataLen = $secondbyte & 127; + $isFinFrame = $firstbyte >> 7; + $masked = $secondbyte >> 7; + + if ($masked) { + Worker::safeEcho("frame masked so close the connection\n"); + $connection->close(); + return 0; + } + + $opcode = $firstbyte & 0xf; + + switch ($opcode) { + case 0x0: + // Blob type. + case 0x1: + // Arraybuffer type. + case 0x2: + // Ping package. + case 0x9: + // Pong package. + case 0xa: + break; + // Close package. + case 0x8: + // Try to emit onWebSocketClose callback. + if (isset($connection->onWebSocketClose)) { + try { + ($connection->onWebSocketClose)($connection); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } // Close connection. + else { + $connection->close(); + } + return 0; + // Wrong opcode. + default : + Worker::safeEcho("error opcode $opcode and close websocket connection. Buffer:" . $buffer . "\n"); + $connection->close(); + return 0; + } + // Calculate packet length. + if ($dataLen === 126) { + if (\strlen($buffer) < 4) { + return 0; + } + $pack = \unpack('nn/ntotal_len', $buffer); + $currentFrameLength = $pack['total_len'] + 4; + } else if ($dataLen === 127) { + if (\strlen($buffer) < 10) { + return 0; + } + $arr = \unpack('n/N2c', $buffer); + $currentFrameLength = $arr['c1'] * 4294967296 + $arr['c2'] + 10; + } else { + $currentFrameLength = $dataLen + 2; + } + + $totalPackageSize = \strlen($connection->context->websocketDataBuffer) + $currentFrameLength; + if ($totalPackageSize > $connection->maxPackageSize) { + Worker::safeEcho("error package. package_length=$totalPackageSize\n"); + $connection->close(); + return 0; + } + + if ($isFinFrame) { + if ($opcode === 0x9) { + if ($recvLen >= $currentFrameLength) { + $pingData = static::decode(\substr($buffer, 0, $currentFrameLength), $connection); + $connection->consumeRecvBuffer($currentFrameLength); + $tmpConnectionType = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB; + $connection->websocketType = "\x8a"; + if (isset($connection->onWebSocketPing)) { + try { + ($connection->onWebSocketPing)($connection, $pingData); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } else { + $connection->send($pingData); + } + $connection->websocketType = $tmpConnectionType; + if ($recvLen > $currentFrameLength) { + return static::input(\substr($buffer, $currentFrameLength), $connection); + } + } + return 0; + + } else if ($opcode === 0xa) { + if ($recvLen >= $currentFrameLength) { + $pongData = static::decode(\substr($buffer, 0, $currentFrameLength), $connection); + $connection->consumeRecvBuffer($currentFrameLength); + $tmpConnectionType = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB; + $connection->websocketType = "\x8a"; + // Try to emit onWebSocketPong callback. + if (isset($connection->onWebSocketPong)) { + try { + ($connection->onWebSocketPong)($connection, $pongData); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + $connection->websocketType = $tmpConnectionType; + if ($recvLen > $currentFrameLength) { + return static::input(\substr($buffer, $currentFrameLength), $connection); + } + } + return 0; + } + return $currentFrameLength; + } else { + $connection->context->websocketCurrentFrameLength = $currentFrameLength; + } + } + // Received just a frame length data. + if ($connection->context->websocketCurrentFrameLength === $recvLen) { + self::decode($buffer, $connection); + $connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength); + $connection->context->websocketCurrentFrameLength = 0; + return 0; + } // The length of the received data is greater than the length of a frame. + elseif ($connection->context->websocketCurrentFrameLength < $recvLen) { + self::decode(\substr($buffer, 0, $connection->context->websocketCurrentFrameLength), $connection); + $connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength); + $currentFrameLength = $connection->context->websocketCurrentFrameLength; + $connection->context->websocketCurrentFrameLength = 0; + // Continue to read next frame. + return self::input(\substr($buffer, $currentFrameLength), $connection); + } // The length of the received data is less than the length of a frame. + else { + return 0; + } + } + + /** + * Websocket encode. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return string + */ + public static function encode($payload, ConnectionInterface $connection) + { + if (empty($connection->websocketType)) { + $connection->websocketType = self::BINARY_TYPE_BLOB; + } + $payload = (string)$payload; + if (empty($connection->context->handshakeStep)) { + static::sendHandshake($connection); + } + + $maskKey = "\x00\x00\x00\x00"; + $length = \strlen($payload); + + if (strlen($payload) < 126) { + $head = chr(0x80 | $length); + } elseif ($length < 0xFFFF) { + $head = chr(0x80 | 126) . pack("n", $length); + } else { + $head = chr(0x80 | 127) . pack("N", 0) . pack("N", $length); + } + + $frame = $connection->websocketType . $head . $maskKey; + // append payload to frame: + $maskKey = \str_repeat($maskKey, \floor($length / 4)) . \substr($maskKey, 0, $length % 4); + $frame .= $payload ^ $maskKey; + if ($connection->context->handshakeStep === 1) { + // If buffer has already full then discard the current package. + if (\strlen($connection->context->tmpWebsocketData) > $connection->maxSendBufferSize) { + if ($connection->onError) { + try { + ($connection->onError)($connection, WORKERMAN_SEND_FAIL, 'send buffer full and drop package'); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + return ''; + } + $connection->context->tmpWebsocketData = $connection->context->tmpWebsocketData . $frame; + // Check buffer is full. + if ($connection->maxSendBufferSize <= \strlen($connection->context->tmpWebsocketData)) { + if ($connection->onBufferFull) { + try { + ($connection->onBufferFull)($connection); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + } + return ''; + } + return $frame; + } + + /** + * Websocket decode. + * + * @param string $buffer + * @param ConnectionInterface $connection + * @return string + */ + public static function decode($bytes, ConnectionInterface $connection) + { + $dataLength = \ord($bytes[1]); + + if ($dataLength === 126) { + $decodedData = \substr($bytes, 4); + } else if ($dataLength === 127) { + $decodedData = \substr($bytes, 10); + } else { + $decodedData = \substr($bytes, 2); + } + if ($connection->context->websocketCurrentFrameLength) { + $connection->context->websocketDataBuffer .= $decodedData; + return $connection->context->websocketDataBuffer; + } else { + if ($connection->context->websocketDataBuffer !== '') { + $decodedData = $connection->context->websocketDataBuffer . $decodedData; + $connection->context->websocketDataBuffer = ''; + } + return $decodedData; + } + } + + /** + * Send websocket handshake data. + * + * @return void + */ + public static function onConnect($connection) + { + static::sendHandshake($connection); + } + + /** + * Clean + * + * @param TcpConnection $connection + */ + public static function onClose($connection) + { + $connection->context->handshakeStep = null; + $connection->context->websocketCurrentFrameLength = 0; + $connection->context->tmpWebsocketData = ''; + $connection->context->websocketDataBuffer = ''; + if (!empty($connection->context->websocketPingTimer)) { + Timer::del($connection->context->websocketPingTimer); + $connection->context->websocketPingTimer = null; + } + } + + /** + * Send websocket handshake. + * + * @param TcpConnection $connection + * @return void + */ + public static function sendHandshake(ConnectionInterface $connection) + { + if (!empty($connection->context->handshakeStep)) { + return; + } + // Get Host. + $port = $connection->getRemotePort(); + $host = $port === 80 ? $connection->getRemoteHost() : $connection->getRemoteHost() . ':' . $port; + // Handshake header. + $connection->context->websocketSecKey = \base64_encode(random_bytes(16)); + $userHeader = $connection->headers ?? null; + $userHeaderStr = ''; + if (!empty($userHeader)) { + if (\is_array($userHeader)) { + foreach ($userHeader as $k => $v) { + $userHeaderStr .= "$k: $v\r\n"; + } + } else { + $userHeaderStr .= $userHeader; + } + $userHeaderStr = "\r\n" . \trim($userHeaderStr); + } + $header = 'GET ' . $connection->getRemoteURI() . " HTTP/1.1\r\n" . + (!\preg_match("/\nHost:/i", $userHeaderStr) ? "Host: $host\r\n" : '') . + "Connection: Upgrade\r\n" . + "Upgrade: websocket\r\n" . + (isset($connection->websocketOrigin) ? "Origin: " . $connection->websocketOrigin . "\r\n" : '') . + (isset($connection->websocketClientProtocol) ? "Sec-WebSocket-Protocol: " . $connection->websocketClientProtocol . "\r\n" : '') . + "Sec-WebSocket-Version: 13\r\n" . + "Sec-WebSocket-Key: " . $connection->context->websocketSecKey . $userHeaderStr . "\r\n\r\n"; + $connection->send($header, true); + $connection->context->handshakeStep = 1; + $connection->context->websocketCurrentFrameLength = 0; + $connection->context->websocketDataBuffer = ''; + $connection->context->tmpWebsocketData = ''; + } + + /** + * Websocket handshake. + * + * @param string $buffer + * @param TcpConnection $connection + * @return int + */ + public static function dealHandshake($buffer, ConnectionInterface $connection) + { + $pos = \strpos($buffer, "\r\n\r\n"); + if ($pos) { + //checking Sec-WebSocket-Accept + if (\preg_match("/Sec-WebSocket-Accept: *(.*?)\r\n/i", $buffer, $match)) { + if ($match[1] !== \base64_encode(\sha1($connection->context->websocketSecKey . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true))) { + Worker::safeEcho("Sec-WebSocket-Accept not match. Header:\n" . \substr($buffer, 0, $pos) . "\n"); + $connection->close(); + return 0; + } + } else { + Worker::safeEcho("Sec-WebSocket-Accept not found. Header:\n" . \substr($buffer, 0, $pos) . "\n"); + $connection->close(); + return 0; + } + + // handshake complete + + // Get WebSocket subprotocol (if specified by server) + if (\preg_match("/Sec-WebSocket-Protocol: *(.*?)\r\n/i", $buffer, $match)) { + $connection->websocketServerProtocol = \trim($match[1]); + } + + $connection->context->handshakeStep = 2; + $handshakeResponseLength = $pos + 4; + // Try to emit onWebSocketConnect callback. + if (isset($connection->onWebSocketConnect)) { + try { + ($connection->onWebSocketConnect)($connection, \substr($buffer, 0, $handshakeResponseLength)); + } catch (\Throwable $e) { + Worker::stopAll(250, $e); + } + } + // Headbeat. + if (!empty($connection->websocketPingInterval)) { + $connection->context->websocketPingTimer = Timer::add($connection->websocketPingInterval, function () use ($connection) { + if (false === $connection->send(\pack('H*', '898000000000'), true)) { + Timer::del($connection->context->websocketPingTimer); + $connection->context->websocketPingTimer = null; + } + }); + } + + $connection->consumeRecvBuffer($handshakeResponseLength); + if (!empty($connection->context->tmpWebsocketData)) { + $connection->send($connection->context->tmpWebsocketData, true); + $connection->context->tmpWebsocketData = ''; + } + if (\strlen($buffer) > $handshakeResponseLength) { + return self::input(\substr($buffer, $handshakeResponseLength), $connection); + } + } + return 0; + } + +} diff --git a/cacme/vendor/workerman/workerman/README.md b/cacme/vendor/workerman/workerman/README.md new file mode 100644 index 0000000..6038c02 --- /dev/null +++ b/cacme/vendor/workerman/workerman/README.md @@ -0,0 +1,342 @@ +# Workerman +[![Gitter](https://badges.gitter.im/walkor/Workerman.svg)](https://gitter.im/walkor/Workerman?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) +[![Latest Stable Version](https://poser.pugx.org/workerman/workerman/v/stable)](https://packagist.org/packages/workerman/workerman) +[![Total Downloads](https://poser.pugx.org/workerman/workerman/downloads)](https://packagist.org/packages/workerman/workerman) +[![Monthly Downloads](https://poser.pugx.org/workerman/workerman/d/monthly)](https://packagist.org/packages/workerman/workerman) +[![Daily Downloads](https://poser.pugx.org/workerman/workerman/d/daily)](https://packagist.org/packages/workerman/workerman) +[![License](https://poser.pugx.org/workerman/workerman/license)](https://packagist.org/packages/workerman/workerman) + +## What is it +Workerman is an asynchronous event-driven PHP framework with high performance to build fast and scalable network applications. +Workerman supports HTTP, Websocket, SSL and other custom protocols. +Workerman supports event extension. + +## Requires +PHP 7.0 or Higher +A POSIX compatible operating system (Linux, OSX, BSD) +POSIX and PCNTL extensions required +Event extension recommended for better performance + +## Installation + +``` +composer require workerman/workerman +``` + +## Basic Usage + +### A websocket server +```php +onConnect = function ($connection) { + echo "New connection\n"; +}; + +// Emitted when data received +$ws_worker->onMessage = function ($connection, $data) { + // Send hello $data + $connection->send('Hello ' . $data); +}; + +// Emitted when connection closed +$ws_worker->onClose = function ($connection) { + echo "Connection closed\n"; +}; + +// Run worker +Worker::runAll(); +``` + +### An http server +```php +count = 4; + +// Emitted when data received +$http_worker->onMessage = function ($connection, $request) { + //$request->get(); + //$request->post(); + //$request->header(); + //$request->cookie(); + //$request->session(); + //$request->uri(); + //$request->path(); + //$request->method(); + + // Send data to client + $connection->send("Hello World"); +}; + +// Run all workers +Worker::runAll(); +``` + +### A tcp server +```php +count = 4; + +// Emitted when new connection come +$tcp_worker->onConnect = function ($connection) { + echo "New Connection\n"; +}; + +// Emitted when data received +$tcp_worker->onMessage = function ($connection, $data) { + // Send data to client + $connection->send("Hello $data \n"); +}; + +// Emitted when connection is closed +$tcp_worker->onClose = function ($connection) { + echo "Connection closed\n"; +}; + +Worker::runAll(); +``` + +### A udp server + +```php +count = 4; + +// Emitted when data received +$worker->onMessage = function($connection, $data) +{ + $connection->send($data); +}; + +Worker::runAll(); +``` + +### Enable SSL +```php + array( + 'local_cert' => '/your/path/of/server.pem', + 'local_pk' => '/your/path/of/server.key', + 'verify_peer' => false, + ) +); + +// Create a Websocket server with ssl context. +$ws_worker = new Worker('websocket://0.0.0.0:2346', $context); + +// Enable SSL. WebSocket+SSL means that Secure WebSocket (wss://). +// The similar approaches for Https etc. +$ws_worker->transport = 'ssl'; + +$ws_worker->onMessage = function ($connection, $data) { + // Send hello $data + $connection->send('Hello ' . $data); +}; + +Worker::runAll(); +``` + +### Custom protocol +Protocols/MyTextProtocol.php +```php +onConnect = function ($connection) { + echo "New connection\n"; +}; + +$text_worker->onMessage = function ($connection, $data) { + // Send data to client + $connection->send("Hello world\n"); +}; + +$text_worker->onClose = function ($connection) { + echo "Connection closed\n"; +}; + +// Run all workers +Worker::runAll(); +``` + +### Timer +```php +onWorkerStart = function ($task) { + // 2.5 seconds + $time_interval = 2.5; + $timer_id = Timer::add($time_interval, function () { + echo "Timer run\n"; + }); +}; + +// Run all workers +Worker::runAll(); +``` + +### AsyncTcpConnection (tcp/ws/text/frame etc...) +```php +onWorkerStart = function () { + // Websocket protocol for client. + $ws_connection = new AsyncTcpConnection('ws://echo.websocket.org:80'); + $ws_connection->onConnect = function ($connection) { + $connection->send('Hello'); + }; + $ws_connection->onMessage = function ($connection, $data) { + echo "Recv: $data\n"; + }; + $ws_connection->onError = function ($connection, $code, $msg) { + echo "Error: $msg\n"; + }; + $ws_connection->onClose = function ($connection) { + echo "Connection closed\n"; + }; + $ws_connection->connect(); +}; + +Worker::runAll(); +``` + + + +## Available commands +```php start.php start ``` +```php start.php start -d ``` +![workerman start](http://www.workerman.net/img/workerman-start.png) +```php start.php status ``` +![workerman satus](http://www.workerman.net/img/workerman-status.png?a=123) +```php start.php connections``` +```php start.php stop ``` +```php start.php restart ``` +```php start.php reload ``` + +## Documentation + +中文主页:[http://www.workerman.net](https://www.workerman.net) + +中文文档: [https://www.workerman.net/doc/workerman](https://www.workerman.net/doc/workerman) + +Documentation:[https://github.com/walkor/workerman-manual](https://github.com/walkor/workerman-manual/blob/master/english/SUMMARY.md) + +# Benchmarks +https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=db&l=yyku7z-e7&a=2 +![image](https://user-images.githubusercontent.com/6073368/146704320-1559fe97-aa67-4ee3-95d6-61e341b3c93b.png) + +## Sponsors +[opencollective.com/walkor](https://opencollective.com/walkor) + +[patreon.com/walkor](https://patreon.com/walkor) + +## Donate + + + +## Other links with workerman + +[webman](https://github.com/walkor/webman) +[PHPSocket.IO](https://github.com/walkor/phpsocket.io) +[php-socks5](https://github.com/walkor/php-socks5) +[php-http-proxy](https://github.com/walkor/php-http-proxy) + +## LICENSE + +Workerman is released under the [MIT license](https://github.com/walkor/workerman/blob/master/MIT-LICENSE.txt). diff --git a/cacme/vendor/workerman/workerman/Timer.php b/cacme/vendor/workerman/workerman/Timer.php new file mode 100644 index 0000000..9f152f3 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Timer.php @@ -0,0 +1,220 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman; + +use Workerman\Events\EventInterface; +use Workerman\Worker; +use \Exception; + +/** + * Timer. + * + * example: + * Workerman\Timer::add($time_interval, callback, array($arg1, $arg2..)); + */ +class Timer +{ + /** + * Tasks that based on ALARM signal. + * [ + * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]], + * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]], + * .. + * ] + * + * @var array + */ + protected static $_tasks = array(); + + /** + * event + * + * @var EventInterface + */ + protected static $_event = null; + + /** + * timer id + * + * @var int + */ + protected static $_timerId = 0; + + /** + * timer status + * [ + * timer_id1 => bool, + * timer_id2 => bool, + * ...................., + * ] + * + * @var array + */ + protected static $_status = array(); + + /** + * Init. + * + * @param EventInterface $event + * @return void + */ + public static function init($event = null) + { + if ($event) { + self::$_event = $event; + return; + } + if (\function_exists('pcntl_signal')) { + \pcntl_signal(\SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false); + } + } + + /** + * ALARM signal handler. + * + * @return void + */ + public static function signalHandle() + { + if (!self::$_event) { + \pcntl_alarm(1); + self::tick(); + } + } + + /** + * Add a timer. + * + * @param float $time_interval + * @param callable $func + * @param mixed $args + * @param bool $persistent + * @return int|bool + */ + public static function add($time_interval, $func, $args = array(), $persistent = true) + { + if ($time_interval <= 0) { + Worker::safeEcho(new Exception("bad time_interval")); + return false; + } + + if ($args === null) { + $args = array(); + } + + if (self::$_event) { + return self::$_event->add($time_interval, + $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args); + } + + // If not workerman runtime just return. + if (!Worker::getAllWorkers()) { + return; + } + + if (!\is_callable($func)) { + Worker::safeEcho(new Exception("not callable")); + return false; + } + + if (empty(self::$_tasks)) { + \pcntl_alarm(1); + } + + $run_time = \time() + $time_interval; + if (!isset(self::$_tasks[$run_time])) { + self::$_tasks[$run_time] = array(); + } + + self::$_timerId = self::$_timerId == \PHP_INT_MAX ? 1 : ++self::$_timerId; + self::$_status[self::$_timerId] = true; + self::$_tasks[$run_time][self::$_timerId] = array($func, (array)$args, $persistent, $time_interval); + + return self::$_timerId; + } + + + /** + * Tick. + * + * @return void + */ + public static function tick() + { + if (empty(self::$_tasks)) { + \pcntl_alarm(0); + return; + } + $time_now = \time(); + foreach (self::$_tasks as $run_time => $task_data) { + if ($time_now >= $run_time) { + foreach ($task_data as $index => $one_task) { + $task_func = $one_task[0]; + $task_args = $one_task[1]; + $persistent = $one_task[2]; + $time_interval = $one_task[3]; + try { + \call_user_func_array($task_func, $task_args); + } catch (\Exception $e) { + Worker::safeEcho($e); + } + if($persistent && !empty(self::$_status[$index])) { + $new_run_time = \time() + $time_interval; + if(!isset(self::$_tasks[$new_run_time])) self::$_tasks[$new_run_time] = array(); + self::$_tasks[$new_run_time][$index] = array($task_func, (array)$task_args, $persistent, $time_interval); + } + } + unset(self::$_tasks[$run_time]); + } + } + } + + /** + * Remove a timer. + * + * @param mixed $timer_id + * @return bool + */ + public static function del($timer_id) + { + if (self::$_event) { + return self::$_event->del($timer_id, EventInterface::EV_TIMER); + } + + foreach(self::$_tasks as $run_time => $task_data) + { + if(array_key_exists($timer_id, $task_data)) unset(self::$_tasks[$run_time][$timer_id]); + } + + if(array_key_exists($timer_id, self::$_status)) unset(self::$_status[$timer_id]); + + return true; + } + + /** + * Remove all timers. + * + * @return void + */ + public static function delAll() + { + self::$_tasks = self::$_status = array(); + if (\function_exists('pcntl_alarm')) { + \pcntl_alarm(0); + } + if (self::$_event) { + self::$_event->clearAllTimer(); + } + } +} diff --git a/cacme/vendor/workerman/workerman/Worker.php b/cacme/vendor/workerman/workerman/Worker.php new file mode 100644 index 0000000..860d728 --- /dev/null +++ b/cacme/vendor/workerman/workerman/Worker.php @@ -0,0 +1,2672 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman; +require_once __DIR__ . '/Lib/Constants.php'; + +use Workerman\Events\EventInterface; +use Workerman\Connection\ConnectionInterface; +use Workerman\Connection\TcpConnection; +use Workerman\Connection\UdpConnection; +use Workerman\Lib\Timer; +use Workerman\Events\Select; +use \Exception; + +/** + * Worker class + * A container for listening ports + */ +#[\AllowDynamicProperties] +class Worker +{ + /** + * Version. + * + * @var string + */ + const VERSION = '4.1.15'; + + /** + * Status starting. + * + * @var int + */ + const STATUS_STARTING = 1; + + /** + * Status running. + * + * @var int + */ + const STATUS_RUNNING = 2; + + /** + * Status shutdown. + * + * @var int + */ + const STATUS_SHUTDOWN = 4; + + /** + * Status reloading. + * + * @var int + */ + const STATUS_RELOADING = 8; + + /** + * Default backlog. Backlog is the maximum length of the queue of pending connections. + * + * @var int + */ + const DEFAULT_BACKLOG = 102400; + + /** + * Max udp package size. + * + * @var int + */ + const MAX_UDP_PACKAGE_SIZE = 65535; + + /** + * The safe distance for columns adjacent + * + * @var int + */ + const UI_SAFE_LENGTH = 4; + + /** + * Worker id. + * + * @var int + */ + public $id = 0; + + /** + * Name of the worker processes. + * + * @var string + */ + public $name = 'none'; + + /** + * Number of worker processes. + * + * @var int + */ + public $count = 1; + + /** + * Unix user of processes, needs appropriate privileges (usually root). + * + * @var string + */ + public $user = ''; + + /** + * Unix group of processes, needs appropriate privileges (usually root). + * + * @var string + */ + public $group = ''; + + /** + * reloadable. + * + * @var bool + */ + public $reloadable = true; + + /** + * reuse port. + * + * @var bool + */ + public $reusePort = false; + + /** + * Emitted when worker processes start. + * + * @var callable + */ + public $onWorkerStart = null; + + /** + * Emitted when a socket connection is successfully established. + * + * @var callable + */ + public $onConnect = null; + + /** + * Emitted when data is received. + * + * @var callable + */ + public $onMessage = null; + + /** + * Emitted when the other end of the socket sends a FIN packet. + * + * @var callable + */ + public $onClose = null; + + /** + * Emitted when an error occurs with connection. + * + * @var callable + */ + public $onError = null; + + /** + * Emitted when the send buffer becomes full. + * + * @var callable + */ + public $onBufferFull = null; + + /** + * Emitted when the send buffer becomes empty. + * + * @var callable + */ + public $onBufferDrain = null; + + /** + * Emitted when worker processes stopped. + * + * @var callable + */ + public $onWorkerStop = null; + + /** + * Emitted when worker processes get reload signal. + * + * @var callable + */ + public $onWorkerReload = null; + + /** + * Emitted when worker processes exited. + * + * @var callable + */ + public $onWorkerExit = null; + + /** + * Transport layer protocol. + * + * @var string + */ + public $transport = 'tcp'; + + /** + * Store all connections of clients. + * + * @var array + */ + public $connections = array(); + + /** + * Application layer protocol. + * + * @var string + */ + public $protocol = null; + + /** + * Root path for autoload. + * + * @var string + */ + protected $_autoloadRootPath = ''; + + /** + * Pause accept new connections or not. + * + * @var bool + */ + protected $_pauseAccept = true; + + /** + * Is worker stopping ? + * @var bool + */ + public $stopping = false; + + /** + * Daemonize. + * + * @var bool + */ + public static $daemonize = false; + + /** + * Stdout file. + * + * @var string + */ + public static $stdoutFile = '/dev/null'; + + /** + * The file to store master process PID. + * + * @var string + */ + public static $pidFile = ''; + + /** + * The file used to store the master process status file. + * + * @var string + */ + public static $statusFile = ''; + + /** + * Log file. + * + * @var mixed + */ + public static $logFile = ''; + + /** + * Global event loop. + * + * @var EventInterface + */ + public static $globalEvent = null; + + /** + * Emitted when the master process get reload signal. + * + * @var callable + */ + public static $onMasterReload = null; + + /** + * Emitted when the master process terminated. + * + * @var callable + */ + public static $onMasterStop = null; + + /** + * EventLoopClass + * + * @var string + */ + public static $eventLoopClass = ''; + + /** + * Process title + * + * @var string + */ + public static $processTitle = 'WorkerMan'; + + /** + * After sending the stop command to the child process stopTimeout seconds, + * if the process is still living then forced to kill. + * + * @var int + */ + public static $stopTimeout = 2; + + /** + * The PID of master process. + * + * @var int + */ + protected static $_masterPid = 0; + + /** + * Listening socket. + * + * @var resource + */ + protected $_mainSocket = null; + + /** + * Socket name. The format is like this http://0.0.0.0:80 . + * + * @var string + */ + protected $_socketName = ''; + + /** parse from _socketName avoid parse again in master or worker + * LocalSocket The format is like tcp://0.0.0.0:8080 + * @var string + */ + + protected $_localSocket=null; + + /** + * Context of socket. + * + * @var resource + */ + protected $_context = null; + + /** + * All worker instances. + * + * @var Worker[] + */ + protected static $_workers = array(); + + /** + * All worker processes pid. + * The format is like this [worker_id=>[pid=>pid, pid=>pid, ..], ..] + * + * @var array + */ + protected static $_pidMap = array(); + + /** + * All worker processes waiting for restart. + * The format is like this [pid=>pid, pid=>pid]. + * + * @var array + */ + protected static $_pidsToRestart = array(); + + /** + * Mapping from PID to worker process ID. + * The format is like this [worker_id=>[0=>$pid, 1=>$pid, ..], ..]. + * + * @var array + */ + protected static $_idMap = array(); + + /** + * Current status. + * + * @var int + */ + protected static $_status = self::STATUS_STARTING; + + /** + * Maximum length of the worker names. + * + * @var int + */ + protected static $_maxWorkerNameLength = 12; + + /** + * Maximum length of the socket names. + * + * @var int + */ + protected static $_maxSocketNameLength = 12; + + /** + * Maximum length of the process user names. + * + * @var int + */ + protected static $_maxUserNameLength = 12; + + /** + * Maximum length of the Proto names. + * + * @var int + */ + protected static $_maxProtoNameLength = 4; + + /** + * Maximum length of the Processes names. + * + * @var int + */ + protected static $_maxProcessesNameLength = 9; + + /** + * Maximum length of the Status names. + * + * @var int + */ + protected static $_maxStatusNameLength = 1; + + /** + * The file to store status info of current worker process. + * + * @var string + */ + protected static $_statisticsFile = ''; + + /** + * Start file. + * + * @var string + */ + protected static $_startFile = ''; + + /** + * OS. + * + * @var string + */ + protected static $_OS = \OS_TYPE_LINUX; + + /** + * Processes for windows. + * + * @var array + */ + protected static $_processForWindows = array(); + + /** + * Status info of current worker process. + * + * @var array + */ + protected static $_globalStatistics = array( + 'start_timestamp' => 0, + 'worker_exit_info' => array() + ); + + /** + * Available event loops. + * + * @var array + */ + protected static $_availableEventLoops = array( + 'event' => '\Workerman\Events\Event', + 'libevent' => '\Workerman\Events\Libevent' + ); + + /** + * PHP built-in protocols. + * + * @var array + */ + protected static $_builtinTransports = array( + 'tcp' => 'tcp', + 'udp' => 'udp', + 'unix' => 'unix', + 'ssl' => 'tcp' + ); + + /** + * PHP built-in error types. + * + * @var array + */ + protected static $_errorType = array( + \E_ERROR => 'E_ERROR', // 1 + \E_WARNING => 'E_WARNING', // 2 + \E_PARSE => 'E_PARSE', // 4 + \E_NOTICE => 'E_NOTICE', // 8 + \E_CORE_ERROR => 'E_CORE_ERROR', // 16 + \E_CORE_WARNING => 'E_CORE_WARNING', // 32 + \E_COMPILE_ERROR => 'E_COMPILE_ERROR', // 64 + \E_COMPILE_WARNING => 'E_COMPILE_WARNING', // 128 + \E_USER_ERROR => 'E_USER_ERROR', // 256 + \E_USER_WARNING => 'E_USER_WARNING', // 512 + \E_USER_NOTICE => 'E_USER_NOTICE', // 1024 + \E_STRICT => 'E_STRICT', // 2048 + \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', // 4096 + \E_DEPRECATED => 'E_DEPRECATED', // 8192 + \E_USER_DEPRECATED => 'E_USER_DEPRECATED' // 16384 + ); + + /** + * Graceful stop or not. + * + * @var bool + */ + protected static $_gracefulStop = false; + + /** + * Standard output stream + * @var resource + */ + protected static $_outputStream = null; + + /** + * If $outputStream support decorated + * @var bool + */ + protected static $_outputDecorated = null; + + /** + * Run all worker instances. + * + * @return void + */ + public static function runAll() + { + static::checkSapiEnv(); + static::init(); + static::parseCommand(); + static::lock(); + static::daemonize(); + static::initWorkers(); + static::installSignal(); + static::saveMasterPid(); + static::lock(\LOCK_UN); + static::displayUI(); + static::forkWorkers(); + static::resetStd(); + static::monitorWorkers(); + } + + /** + * Check sapi. + * + * @return void + */ + protected static function checkSapiEnv() + { + // Only for cli and micro. + if (!in_array(\PHP_SAPI, ['cli', 'micro'])) { + exit("Only run in command line mode \n"); + } + if (\DIRECTORY_SEPARATOR === '\\') { + self::$_OS = \OS_TYPE_WINDOWS; + } + } + + /** + * Init. + * + * @return void + */ + protected static function init() + { + \set_error_handler(function($code, $msg, $file, $line){ + Worker::safeEcho("$msg in file $file on line $line\n"); + }); + + // Start file. + $backtrace = \debug_backtrace(); + static::$_startFile = $backtrace[\count($backtrace) - 1]['file']; + + + $unique_prefix = \str_replace('/', '_', static::$_startFile); + + // Pid file. + if (empty(static::$pidFile)) { + static::$pidFile = __DIR__ . "/../$unique_prefix.pid"; + } + + // Log file. + if (empty(static::$logFile)) { + static::$logFile = __DIR__ . '/../workerman.log'; + } + $log_file = (string)static::$logFile; + if (!\is_file($log_file)) { + \touch($log_file); + \chmod($log_file, 0622); + } + + // State. + static::$_status = static::STATUS_STARTING; + + // For statistics. + static::$_globalStatistics['start_timestamp'] = \time(); + + // Process title. + static::setProcessTitle(static::$processTitle . ': master process start_file=' . static::$_startFile); + + // Init data for worker id. + static::initId(); + + // Timer init. + Timer::init(); + } + + /** + * Lock. + * + * @return void + */ + protected static function lock($flag = \LOCK_EX) + { + static $fd; + if (\DIRECTORY_SEPARATOR !== '/') { + return; + } + $lock_file = static::$pidFile . '.lock'; + $fd = $fd ?: \fopen($lock_file, 'a+'); + if ($fd) { + flock($fd, $flag); + if ($flag === \LOCK_UN) { + fclose($fd); + $fd = null; + clearstatcache(); + if (\is_file($lock_file)) { + unlink($lock_file); + } + } + } + } + + /** + * Init All worker instances. + * + * @return void + */ + protected static function initWorkers() + { + if (static::$_OS !== \OS_TYPE_LINUX) { + return; + } + + static::$_statisticsFile = static::$statusFile ? static::$statusFile : __DIR__ . '/../workerman-' .posix_getpid().'.status'; + + foreach (static::$_workers as $worker) { + // Worker name. + if (empty($worker->name)) { + $worker->name = 'none'; + } + + // Get unix user of the worker process. + if (empty($worker->user)) { + $worker->user = static::getCurrentUser(); + } else { + if (\posix_getuid() !== 0 && $worker->user !== static::getCurrentUser()) { + static::log('Warning: You must have the root privileges to change uid and gid.'); + } + } + + // Socket name. + $worker->socket = $worker->getSocketName(); + + // Status name. + $worker->status = ' [OK] '; + + // Get column mapping for UI + foreach(static::getUiColumns() as $column_name => $prop){ + !isset($worker->{$prop}) && $worker->{$prop} = 'NNNN'; + $prop_length = \strlen((string) $worker->{$prop}); + $key = '_max' . \ucfirst(\strtolower($column_name)) . 'NameLength'; + static::$$key = \max(static::$$key, $prop_length); + } + + // Listen. + if (!$worker->reusePort) { + $worker->listen(); + } + } + } + + /** + * Reload all worker instances. + * + * @return void + */ + public static function reloadAllWorkers() + { + static::init(); + static::initWorkers(); + static::displayUI(); + static::$_status = static::STATUS_RELOADING; + } + + /** + * Get all worker instances. + * + * @return array + */ + public static function getAllWorkers() + { + return static::$_workers; + } + + /** + * Get global event-loop instance. + * + * @return EventInterface + */ + public static function getEventLoop() + { + return static::$globalEvent; + } + + /** + * Get main socket resource + * @return resource + */ + public function getMainSocket(){ + return $this->_mainSocket; + } + + /** + * Init idMap. + * return void + */ + protected static function initId() + { + foreach (static::$_workers as $worker_id => $worker) { + $new_id_map = array(); + $worker->count = $worker->count < 1 ? 1 : $worker->count; + for($key = 0; $key < $worker->count; $key++) { + $new_id_map[$key] = isset(static::$_idMap[$worker_id][$key]) ? static::$_idMap[$worker_id][$key] : 0; + } + static::$_idMap[$worker_id] = $new_id_map; + } + } + + /** + * Get unix user of current porcess. + * + * @return string + */ + protected static function getCurrentUser() + { + $user_info = \posix_getpwuid(\posix_getuid()); + return $user_info['name'] ?? 'unknown'; + } + + /** + * Display staring UI. + * + * @return void + */ + protected static function displayUI() + { + global $argv; + if (\in_array('-q', $argv)) { + return; + } + if (static::$_OS !== \OS_TYPE_LINUX) { + static::safeEcho("---------------------------------------------- WORKERMAN -----------------------------------------------\r\n"); + static::safeEcho('Workerman version:'. static::VERSION. ' PHP version:'. \PHP_VERSION. "\r\n"); + static::safeEcho("----------------------------------------------- WORKERS ------------------------------------------------\r\n"); + static::safeEcho("worker listen processes status\r\n"); + return; + } + + //show version + $line_version = 'Workerman version:' . static::VERSION . \str_pad('PHP version:', 22, ' ', \STR_PAD_LEFT) . \PHP_VERSION; + $line_version .= \str_pad('Event-Loop:', 22, ' ', \STR_PAD_LEFT) . static::getEventLoopName() . \PHP_EOL; + !\defined('LINE_VERSIOIN_LENGTH') && \define('LINE_VERSIOIN_LENGTH', \strlen($line_version)); + $total_length = static::getSingleLineTotalLength(); + $line_one = '' . \str_pad(' WORKERMAN ', $total_length + \strlen(''), '-', \STR_PAD_BOTH) . ''. \PHP_EOL; + $line_two = \str_pad(' WORKERS ' , $total_length + \strlen(''), '-', \STR_PAD_BOTH) . \PHP_EOL; + static::safeEcho($line_one . $line_version . $line_two); + + //Show title + $title = ''; + foreach(static::getUiColumns() as $column_name => $prop){ + $key = '_max' . \ucfirst(\strtolower($column_name)) . 'NameLength'; + //just keep compatible with listen name + $column_name === 'socket' && $column_name = 'listen'; + $title.= "{$column_name}" . \str_pad('', static::$$key + static::UI_SAFE_LENGTH - \strlen($column_name)); + } + $title && static::safeEcho($title . \PHP_EOL); + + //Show content + foreach (static::$_workers as $worker) { + $content = ''; + foreach(static::getUiColumns() as $column_name => $prop){ + $key = '_max' . \ucfirst(\strtolower($column_name)) . 'NameLength'; + \preg_match_all("/(|<\/n>||<\/w>||<\/g>)/is", (string) $worker->{$prop}, $matches); + $place_holder_length = !empty($matches) ? \strlen(\implode('', $matches[0])) : 0; + $content .= \str_pad((string) $worker->{$prop}, static::$$key + static::UI_SAFE_LENGTH + $place_holder_length); + } + $content && static::safeEcho($content . \PHP_EOL); + } + + //Show last line + $line_last = \str_pad('', static::getSingleLineTotalLength(), '-') . \PHP_EOL; + !empty($content) && static::safeEcho($line_last); + + if (static::$daemonize) { + $tmpArgv = $argv; + foreach ($tmpArgv as $index => $value) { + if ($value == '-d') { + unset($tmpArgv[$index]); + } elseif ($value == 'start' || $value == 'restart') { + $tmpArgv[$index] = 'stop'; + } + } + static::safeEcho("Input \"php ".implode(' ', $tmpArgv)."\" to stop. Start success.\n\n"); + } else { + static::safeEcho("Press Ctrl+C to stop. Start success.\n"); + } + } + + /** + * Get UI columns to be shown in terminal + * + * 1. $column_map: array('ui_column_name' => 'clas_property_name') + * 2. Consider move into configuration in future + * + * @return array + */ + public static function getUiColumns() + { + return array( + 'proto' => 'transport', + 'user' => 'user', + 'worker' => 'name', + 'socket' => 'socket', + 'processes' => 'count', + 'status' => 'status', + ); + } + + /** + * Get single line total length for ui + * + * @return int + */ + public static function getSingleLineTotalLength() + { + $total_length = 0; + + foreach(static::getUiColumns() as $column_name => $prop){ + $key = '_max' . \ucfirst(\strtolower($column_name)) . 'NameLength'; + $total_length += static::$$key + static::UI_SAFE_LENGTH; + } + + //keep beauty when show less colums + !\defined('LINE_VERSIOIN_LENGTH') && \define('LINE_VERSIOIN_LENGTH', 0); + $total_length <= LINE_VERSIOIN_LENGTH && $total_length = LINE_VERSIOIN_LENGTH; + + return $total_length; + } + + /** + * Parse command. + * + * @return void + */ + protected static function parseCommand() + { + if (static::$_OS !== \OS_TYPE_LINUX) { + return; + } + global $argv; + // Check argv; + $start_file = $argv[0]; + $usage = "Usage: php yourfile [mode]\nCommands: \nstart\t\tStart worker in DEBUG mode.\n\t\tUse mode -d to start in DAEMON mode.\nstop\t\tStop worker.\n\t\tUse mode -g to stop gracefully.\nrestart\t\tRestart workers.\n\t\tUse mode -d to start in DAEMON mode.\n\t\tUse mode -g to stop gracefully.\nreload\t\tReload codes.\n\t\tUse mode -g to reload gracefully.\nstatus\t\tGet worker status.\n\t\tUse mode -d to show live status.\nconnections\tGet worker connections.\n"; + $available_commands = array( + 'start', + 'stop', + 'restart', + 'reload', + 'status', + 'connections', + ); + $available_mode = array( + '-d', + '-g' + ); + $command = $mode = ''; + foreach ($argv as $value) { + if (\in_array($value, $available_commands)) { + $command = $value; + } elseif (\in_array($value, $available_mode)) { + $mode = $value; + } + } + + if (!$command) { + exit($usage); + } + + // Start command. + $mode_str = ''; + if ($command === 'start') { + if ($mode === '-d' || static::$daemonize) { + $mode_str = 'in DAEMON mode'; + } else { + $mode_str = 'in DEBUG mode'; + } + } + static::log("Workerman[$start_file] $command $mode_str"); + + // Get master process PID. + $master_pid = \is_file(static::$pidFile) ? (int)\file_get_contents(static::$pidFile) : 0; + // Master is still alive? + if (static::checkMasterIsAlive($master_pid)) { + if ($command === 'start') { + static::log("Workerman[$start_file] already running"); + exit; + } + } elseif ($command !== 'start' && $command !== 'restart') { + static::log("Workerman[$start_file] not run"); + exit; + } + + $statistics_file = static::$statusFile ? static::$statusFile : __DIR__ . "/../workerman-$master_pid.status"; + + // execute command. + switch ($command) { + case 'start': + if ($mode === '-d') { + static::$daemonize = true; + } + break; + case 'status': + while (1) { + if (\is_file($statistics_file)) { + @\unlink($statistics_file); + } + // Master process will send SIGIOT signal to all child processes. + \posix_kill($master_pid, SIGIOT); + // Sleep 1 second. + \sleep(1); + // Clear terminal. + if ($mode === '-d') { + static::safeEcho("\33[H\33[2J\33(B\33[m", true); + } + // Echo status data. + static::safeEcho(static::formatStatusData($statistics_file)); + if ($mode !== '-d') { + exit(0); + } + static::safeEcho("\nPress Ctrl+C to quit.\n\n"); + } + exit(0); + case 'connections': + if (\is_file($statistics_file) && \is_writable($statistics_file)) { + \unlink($statistics_file); + } + // Master process will send SIGIO signal to all child processes. + \posix_kill($master_pid, SIGIO); + // Waiting amoment. + \usleep(500000); + // Display statisitcs data from a disk file. + if(\is_readable($statistics_file)) { + \readfile($statistics_file); + } + exit(0); + case 'restart': + case 'stop': + if ($mode === '-g') { + static::$_gracefulStop = true; + $sig = \SIGQUIT; + static::log("Workerman[$start_file] is gracefully stopping ..."); + } else { + static::$_gracefulStop = false; + $sig = \SIGINT; + static::log("Workerman[$start_file] is stopping ..."); + } + // Send stop signal to master process. + $master_pid && \posix_kill($master_pid, $sig); + // Timeout. + $timeout = static::$stopTimeout + 3; + $start_time = \time(); + // Check master process is still alive? + while (1) { + $master_is_alive = $master_pid && \posix_kill((int) $master_pid, 0); + if ($master_is_alive) { + // Timeout? + if (!static::$_gracefulStop && \time() - $start_time >= $timeout) { + static::log("Workerman[$start_file] stop fail"); + exit; + } + // Waiting amoment. + \usleep(10000); + continue; + } + // Stop success. + static::log("Workerman[$start_file] stop success"); + if ($command === 'stop') { + exit(0); + } + if ($mode === '-d') { + static::$daemonize = true; + } + break; + } + break; + case 'reload': + if($mode === '-g'){ + $sig = \SIGUSR2; + }else{ + $sig = \SIGUSR1; + } + \posix_kill($master_pid, $sig); + exit; + default : + if (isset($command)) { + static::safeEcho('Unknown command: ' . $command . "\n"); + } + exit($usage); + } + } + + /** + * Format status data. + * + * @param $statistics_file + * @return string + */ + protected static function formatStatusData($statistics_file) + { + static $total_request_cache = array(); + if (!\is_readable($statistics_file)) { + return ''; + } + $info = \file($statistics_file, \FILE_IGNORE_NEW_LINES); + if (!$info) { + return ''; + } + $status_str = ''; + $current_total_request = array(); + $workerInfo = []; + try { + $workerInfo = unserialize($info[0], ['allowed_classes' => false]); + } catch (Throwable $exception) {} + if (!is_array($workerInfo)) { + $workerInfo = []; + } + \ksort($workerInfo, SORT_NUMERIC); + unset($info[0]); + $data_waiting_sort = array(); + $read_process_status = false; + $total_requests = 0; + $total_qps = 0; + $total_connections = 0; + $total_fails = 0; + $total_memory = 0; + $total_timers = 0; + $maxLen1 = static::$_maxSocketNameLength; + $maxLen2 = static::$_maxWorkerNameLength; + foreach($info as $key => $value) { + if (!$read_process_status) { + $status_str .= $value . "\n"; + if (\preg_match('/^pid.*?memory.*?listening/', $value)) { + $read_process_status = true; + } + continue; + } + if(\preg_match('/^[0-9]+/', $value, $pid_math)) { + $pid = $pid_math[0]; + $data_waiting_sort[$pid] = $value; + if(\preg_match('/^\S+?\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?/', $value, $match)) { + $total_memory += \intval(\str_ireplace('M','',$match[1])); + $maxLen1 = \max($maxLen1,\strlen($match[2])); + $maxLen2 = \max($maxLen2,\strlen($match[3])); + $total_connections += \intval($match[4]); + $total_fails += \intval($match[5]); + $total_timers += \intval($match[6]); + $current_total_request[$pid] = $match[7]; + $total_requests += \intval($match[7]); + } + } + } + foreach($workerInfo as $pid => $info) { + if (!isset($data_waiting_sort[$pid])) { + $status_str .= "$pid\t" . \str_pad('N/A', 7) . " " + . \str_pad($info['listen'], static::$_maxSocketNameLength) . " " + . \str_pad($info['name'], static::$_maxWorkerNameLength) . " " + . \str_pad('N/A', 11) . " " . \str_pad('N/A', 9) . " " + . \str_pad('N/A', 7) . " " . \str_pad('N/A', 13) . " N/A [busy] \n"; + continue; + } + //$qps = isset($total_request_cache[$pid]) ? $current_total_request[$pid] + if (!isset($total_request_cache[$pid]) || !isset($current_total_request[$pid])) { + $qps = 0; + } else { + $qps = $current_total_request[$pid] - $total_request_cache[$pid]; + $total_qps += $qps; + } + $status_str .= $data_waiting_sort[$pid]. " " . \str_pad($qps, 6) ." [idle]\n"; + } + $total_request_cache = $current_total_request; + $status_str .= "----------------------------------------------PROCESS STATUS---------------------------------------------------\n"; + $status_str .= "Summary\t" . \str_pad($total_memory.'M', 7) . " " + . \str_pad('-', $maxLen1) . " " + . \str_pad('-', $maxLen2) . " " + . \str_pad($total_connections, 11) . " " . \str_pad($total_fails, 9) . " " + . \str_pad($total_timers, 7) . " " . \str_pad($total_requests, 13) . " " + . \str_pad($total_qps,6)." [Summary] \n"; + return $status_str; + } + + + /** + * Install signal handler. + * + * @return void + */ + protected static function installSignal() + { + if (static::$_OS !== \OS_TYPE_LINUX) { + return; + } + $signalHandler = '\Workerman\Worker::signalHandler'; + // stop + \pcntl_signal(\SIGINT, $signalHandler, false); + // stop + \pcntl_signal(\SIGTERM, $signalHandler, false); + // stop + \pcntl_signal(\SIGHUP, $signalHandler, false); + // stop + \pcntl_signal(\SIGTSTP, $signalHandler, false); + // graceful stop + \pcntl_signal(\SIGQUIT, $signalHandler, false); + // reload + \pcntl_signal(\SIGUSR1, $signalHandler, false); + // graceful reload + \pcntl_signal(\SIGUSR2, $signalHandler, false); + // status + \pcntl_signal(\SIGIOT, $signalHandler, false); + // connection status + \pcntl_signal(\SIGIO, $signalHandler, false); + // ignore + \pcntl_signal(\SIGPIPE, \SIG_IGN, false); + } + + /** + * Reinstall signal handler. + * + * @return void + */ + protected static function reinstallSignal() + { + if (static::$_OS !== \OS_TYPE_LINUX) { + return; + } + $signalHandler = '\Workerman\Worker::signalHandler'; + // uninstall stop signal handler + \pcntl_signal(\SIGINT, \SIG_IGN, false); + // uninstall stop signal handler + \pcntl_signal(\SIGTERM, \SIG_IGN, false); + // uninstall stop signal handler + \pcntl_signal(\SIGHUP, \SIG_IGN, false); + // uninstall stop signal handler + \pcntl_signal(\SIGTSTP, \SIG_IGN, false); + // uninstall graceful stop signal handler + \pcntl_signal(\SIGQUIT, \SIG_IGN, false); + // uninstall reload signal handler + \pcntl_signal(\SIGUSR1, \SIG_IGN, false); + // uninstall graceful reload signal handler + \pcntl_signal(\SIGUSR2, \SIG_IGN, false); + // uninstall status signal handler + \pcntl_signal(\SIGIOT, \SIG_IGN, false); + // uninstall connections status signal handler + \pcntl_signal(\SIGIO, \SIG_IGN, false); + // reinstall stop signal handler + static::$globalEvent->add(\SIGINT, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall graceful stop signal handler + static::$globalEvent->add(\SIGQUIT, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall graceful stop signal handler + static::$globalEvent->add(\SIGHUP, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall graceful stop signal handler + static::$globalEvent->add(\SIGTSTP, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall reload signal handler + static::$globalEvent->add(\SIGUSR1, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall graceful reload signal handler + static::$globalEvent->add(\SIGUSR2, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall status signal handler + static::$globalEvent->add(\SIGIOT, EventInterface::EV_SIGNAL, $signalHandler); + // reinstall connection status signal handler + static::$globalEvent->add(\SIGIO, EventInterface::EV_SIGNAL, $signalHandler); + } + + /** + * Signal handler. + * + * @param int $signal + */ + public static function signalHandler($signal) + { + switch ($signal) { + // Stop. + case \SIGINT: + case \SIGTERM: + case \SIGHUP: + case \SIGTSTP: + static::$_gracefulStop = false; + static::stopAll(); + break; + // Graceful stop. + case \SIGQUIT: + static::$_gracefulStop = true; + static::stopAll(); + break; + // Reload. + case \SIGUSR2: + case \SIGUSR1: + if (static::$_status === static::STATUS_SHUTDOWN || static::$_status === static::STATUS_RELOADING) { + return; + } + static::$_gracefulStop = $signal === \SIGUSR2; + static::$_pidsToRestart = static::getAllWorkerPids(); + static::reload(); + break; + // Show status. + case \SIGIOT: + static::writeStatisticsToStatusFile(); + break; + // Show connection status. + case \SIGIO: + static::writeConnectionsStatisticsToStatusFile(); + break; + } + } + + /** + * Run as daemon mode. + * + * @throws Exception + */ + protected static function daemonize() + { + if (!static::$daemonize || static::$_OS !== \OS_TYPE_LINUX) { + return; + } + \umask(0); + $pid = \pcntl_fork(); + if (-1 === $pid) { + throw new Exception('Fork fail'); + } elseif ($pid > 0) { + exit(0); + } + if (-1 === \posix_setsid()) { + throw new Exception("Setsid fail"); + } + // Fork again avoid SVR4 system regain the control of terminal. + $pid = \pcntl_fork(); + if (-1 === $pid) { + throw new Exception("Fork fail"); + } elseif (0 !== $pid) { + exit(0); + } + } + + /** + * Redirect standard input and output. + * + * @throws Exception + */ + public static function resetStd() + { + if (!static::$daemonize || \DIRECTORY_SEPARATOR !== '/') { + return; + } + global $STDOUT, $STDERR; + $handle = \fopen(static::$stdoutFile, "a"); + if ($handle) { + unset($handle); + \set_error_handler(function(){}); + if ($STDOUT) { + \fclose($STDOUT); + } + if ($STDERR) { + \fclose($STDERR); + } + if (\is_resource(\STDOUT)) { + \fclose(\STDOUT); + } + if (\is_resource(\STDERR)) { + \fclose(\STDERR); + } + $STDOUT = \fopen(static::$stdoutFile, "a"); + $STDERR = \fopen(static::$stdoutFile, "a"); + // Fix standard output cannot redirect of PHP 8.1.8's bug + if (\function_exists('posix_isatty') && \posix_isatty(2)) { + \ob_start(function ($string) { + \file_put_contents(static::$stdoutFile, $string, FILE_APPEND); + }, 1); + } + // change output stream + static::$_outputStream = null; + static::outputStream($STDOUT); + \restore_error_handler(); + return; + } + + throw new Exception('Can not open stdoutFile ' . static::$stdoutFile); + } + + /** + * Save pid. + * + * @throws Exception + */ + protected static function saveMasterPid() + { + if (static::$_OS !== \OS_TYPE_LINUX) { + return; + } + + static::$_masterPid = \posix_getpid(); + if (false === \file_put_contents(static::$pidFile, static::$_masterPid)) { + throw new Exception('can not save pid to ' . static::$pidFile); + } + } + + /** + * Get event loop name. + * + * @return string + */ + protected static function getEventLoopName() + { + if (static::$eventLoopClass) { + return static::$eventLoopClass; + } + + if (!\class_exists('\Swoole\Event', false)) { + unset(static::$_availableEventLoops['swoole']); + } + + $loop_name = ''; + foreach (static::$_availableEventLoops as $name=>$class) { + if (\extension_loaded($name)) { + $loop_name = $name; + break; + } + } + + if ($loop_name) { + static::$eventLoopClass = static::$_availableEventLoops[$loop_name]; + } else { + static::$eventLoopClass = '\Workerman\Events\Select'; + } + return static::$eventLoopClass; + } + + /** + * Get all pids of worker processes. + * + * @return array + */ + protected static function getAllWorkerPids() + { + $pid_array = array(); + foreach (static::$_pidMap as $worker_pid_array) { + foreach ($worker_pid_array as $worker_pid) { + $pid_array[$worker_pid] = $worker_pid; + } + } + return $pid_array; + } + + /** + * Fork some worker processes. + * + * @return void + */ + protected static function forkWorkers() + { + if (static::$_OS === \OS_TYPE_LINUX) { + static::forkWorkersForLinux(); + } else { + static::forkWorkersForWindows(); + } + } + + /** + * Fork some worker processes. + * + * @return void + */ + protected static function forkWorkersForLinux() + { + + foreach (static::$_workers as $worker) { + if (static::$_status === static::STATUS_STARTING) { + if (empty($worker->name)) { + $worker->name = $worker->getSocketName(); + } + $worker_name_length = \strlen($worker->name); + if (static::$_maxWorkerNameLength < $worker_name_length) { + static::$_maxWorkerNameLength = $worker_name_length; + } + } + + while (\count(static::$_pidMap[$worker->workerId]) < $worker->count) { + static::forkOneWorkerForLinux($worker); + } + } + } + + /** + * Fork some worker processes. + * + * @return void + */ + protected static function forkWorkersForWindows() + { + $files = static::getStartFilesForWindows(); + global $argv; + if(\in_array('-q', $argv) || \count($files) === 1) + { + if(\count(static::$_workers) > 1) + { + static::safeEcho("@@@ Error: multi workers init in one php file are not support @@@\r\n"); + static::safeEcho("@@@ See http://doc.workerman.net/faq/multi-woker-for-windows.html @@@\r\n"); + } + elseif(\count(static::$_workers) <= 0) + { + exit("@@@no worker inited@@@\r\n\r\n"); + } + + \reset(static::$_workers); + /** @var Worker $worker */ + $worker = current(static::$_workers); + + \Workerman\Timer::delAll(); + + //Update process state. + static::$_status = static::STATUS_RUNNING; + + // Register shutdown function for checking errors. + \register_shutdown_function([__CLASS__, 'checkErrors']); + + // Create a global event loop. + if (!static::$globalEvent) { + $eventLoopClass = static::getEventLoopName(); + static::$globalEvent = new $eventLoopClass; + } + + // Reinstall signal. + static::reinstallSignal(); + + // Init Timer. + Timer::init(static::$globalEvent); + + \restore_error_handler(); + + // Add an empty timer to prevent the event-loop from exiting. + Timer::add(1000000, function (){}); + + // Display UI. + static::safeEcho(\str_pad($worker->name, 48) . \str_pad($worker->getSocketName(), 36) . \str_pad('1', 10) . " [ok]\n"); + $worker->listen(); + $worker->run(); + static::$globalEvent->loop(); + if (static::$_status !== self::STATUS_SHUTDOWN) { + $err = new Exception('event-loop exited'); + static::log($err); + exit(250); + } + exit(0); + } + else + { + static::$globalEvent = new \Workerman\Events\Select(); + Timer::init(static::$globalEvent); + foreach($files as $start_file) + { + static::forkOneWorkerForWindows($start_file); + } + } + } + + /** + * Get start files for windows. + * + * @return array + */ + public static function getStartFilesForWindows() { + global $argv; + $files = array(); + foreach($argv as $file) + { + if(\is_file($file)) + { + $files[$file] = $file; + } + } + return $files; + } + + /** + * Fork one worker process. + * + * @param string $start_file + */ + public static function forkOneWorkerForWindows($start_file) + { + $start_file = \realpath($start_file); + + $descriptorspec = array( + STDIN, STDOUT, STDOUT + ); + + $pipes = array(); + $process = \proc_open("php \"$start_file\" -q", $descriptorspec, $pipes); + + if (empty(static::$globalEvent)) { + static::$globalEvent = new Select(); + Timer::init(static::$globalEvent); + } + + // 保存子进程句柄 + static::$_processForWindows[$start_file] = array($process, $start_file); + } + + /** + * check worker status for windows. + * @return void + */ + public static function checkWorkerStatusForWindows() + { + foreach(static::$_processForWindows as $process_data) + { + $process = $process_data[0]; + $start_file = $process_data[1]; + $status = \proc_get_status($process); + if(isset($status['running'])) + { + if(!$status['running']) + { + static::safeEcho("process $start_file terminated and try to restart\n"); + \proc_close($process); + static::forkOneWorkerForWindows($start_file); + } + } + else + { + static::safeEcho("proc_get_status fail\n"); + } + } + } + + + /** + * Fork one worker process. + * + * @param self $worker + * @throws Exception + */ + protected static function forkOneWorkerForLinux(self $worker) + { + // Get available worker id. + $id = static::getId($worker->workerId, 0); + if ($id === false) { + return; + } + $pid = \pcntl_fork(); + // For master process. + if ($pid > 0) { + static::$_pidMap[$worker->workerId][$pid] = $pid; + static::$_idMap[$worker->workerId][$id] = $pid; + } // For child processes. + elseif (0 === $pid) { + \srand(); + \mt_srand(); + static::$_gracefulStop = false; + if (static::$_status === static::STATUS_STARTING) { + static::resetStd(); + } + static::$_pidMap = array(); + // Remove other listener. + foreach(static::$_workers as $key => $one_worker) { + if ($one_worker->workerId !== $worker->workerId) { + $one_worker->unlisten(); + unset(static::$_workers[$key]); + } + } + Timer::delAll(); + //Update process state. + static::$_status = static::STATUS_RUNNING; + + // Register shutdown function for checking errors. + \register_shutdown_function(array("\\Workerman\\Worker", 'checkErrors')); + + // Create a global event loop. + if (!static::$globalEvent) { + $event_loop_class = static::getEventLoopName(); + static::$globalEvent = new $event_loop_class; + } + + // Reinstall signal. + static::reinstallSignal(); + + // Init Timer. + Timer::init(static::$globalEvent); + + \restore_error_handler(); + + static::setProcessTitle(self::$processTitle . ': worker process ' . $worker->name . ' ' . $worker->getSocketName()); + $worker->setUserAndGroup(); + $worker->id = $id; + $worker->run(); + // Main loop. + static::$globalEvent->loop(); + if (strpos(static::$eventLoopClass, 'Workerman\Events\Swoole') !== false) { + exit(0); + } + $err = new Exception('event-loop exited'); + static::log($err); + exit(250); + } else { + throw new Exception("forkOneWorker fail"); + } + } + + /** + * Get worker id. + * + * @param string $worker_id + * @param int $pid + * + * @return integer + */ + protected static function getId($worker_id, $pid) + { + return \array_search($pid, static::$_idMap[$worker_id]); + } + + /** + * Set unix user and group for current process. + * + * @return void + */ + public function setUserAndGroup() + { + // Get uid. + $user_info = \posix_getpwnam($this->user); + if (!$user_info) { + static::log("Warning: User {$this->user} not exists"); + return; + } + $uid = $user_info['uid']; + // Get gid. + if ($this->group) { + $group_info = \posix_getgrnam($this->group); + if (!$group_info) { + static::log("Warning: Group {$this->group} not exists"); + return; + } + $gid = $group_info['gid']; + } else { + $gid = $user_info['gid']; + } + + // Set uid and gid. + if ($uid !== \posix_getuid() || $gid !== \posix_getgid()) { + if (!\posix_setgid($gid) || !\posix_initgroups($user_info['name'], $gid) || !\posix_setuid($uid)) { + static::log("Warning: change gid or uid fail."); + } + } + } + + /** + * Set process name. + * + * @param string $title + * @return void + */ + protected static function setProcessTitle($title) + { + \set_error_handler(function(){}); + // >=php 5.5 + if (\function_exists('cli_set_process_title')) { + \cli_set_process_title($title); + } // Need proctitle when php<=5.5 . + elseif (\extension_loaded('proctitle') && \function_exists('setproctitle')) { + \setproctitle($title); + } + \restore_error_handler(); + } + + /** + * Monitor all child processes. + * + * @return void + */ + protected static function monitorWorkers() + { + if (static::$_OS === \OS_TYPE_LINUX) { + static::monitorWorkersForLinux(); + } else { + static::monitorWorkersForWindows(); + } + } + + /** + * Monitor all child processes. + * + * @return void + */ + protected static function monitorWorkersForLinux() + { + static::$_status = static::STATUS_RUNNING; + while (1) { + // Calls signal handlers for pending signals. + \pcntl_signal_dispatch(); + // Suspends execution of the current process until a child has exited, or until a signal is delivered + $status = 0; + $pid = \pcntl_wait($status, \WUNTRACED); + // Calls signal handlers for pending signals again. + \pcntl_signal_dispatch(); + // If a child has already exited. + if ($pid > 0) { + // Find out which worker process exited. + foreach (static::$_pidMap as $worker_id => $worker_pid_array) { + if (isset($worker_pid_array[$pid])) { + $worker = static::$_workers[$worker_id]; + // Fix exit with status 2 for php8.2 + if ($status === \SIGINT && static::$_status === static::STATUS_SHUTDOWN) { + $status = 0; + } + // Exit status. + if ($status !== 0) { + static::log("worker[{$worker->name}:$pid] exit with status $status"); + } + + // onWorkerExit + if ($worker->onWorkerExit) { + try { + ($worker->onWorkerExit)($worker, $status, $pid); + } catch (\Throwable $exception) { + static::log("worker[{$worker->name}] onWorkerExit $exception"); + } + } + + // For Statistics. + if (!isset(static::$_globalStatistics['worker_exit_info'][$worker_id][$status])) { + static::$_globalStatistics['worker_exit_info'][$worker_id][$status] = 0; + } + ++static::$_globalStatistics['worker_exit_info'][$worker_id][$status]; + + // Clear process data. + unset(static::$_pidMap[$worker_id][$pid]); + + // Mark id is available. + $id = static::getId($worker_id, $pid); + static::$_idMap[$worker_id][$id] = 0; + + break; + } + } + // Is still running state then fork a new worker process. + if (static::$_status !== static::STATUS_SHUTDOWN) { + static::forkWorkers(); + // If reloading continue. + if (isset(static::$_pidsToRestart[$pid])) { + unset(static::$_pidsToRestart[$pid]); + static::reload(); + } + } + } + + // If shutdown state and all child processes exited then master process exit. + if (static::$_status === static::STATUS_SHUTDOWN && !static::getAllWorkerPids()) { + static::exitAndClearAll(); + } + } + } + + /** + * Monitor all child processes. + * + * @return void + */ + protected static function monitorWorkersForWindows() + { + Timer::add(1, "\\Workerman\\Worker::checkWorkerStatusForWindows"); + + static::$globalEvent->loop(); + } + + /** + * Exit current process. + * + * @return void + */ + protected static function exitAndClearAll() + { + foreach (static::$_workers as $worker) { + $socket_name = $worker->getSocketName(); + if ($worker->transport === 'unix' && $socket_name) { + list(, $address) = \explode(':', $socket_name, 2); + $address = substr($address, strpos($address, '/') + 2); + @\unlink($address); + } + } + @\unlink(static::$pidFile); + static::log("Workerman[" . \basename(static::$_startFile) . "] has been stopped"); + if (static::$onMasterStop) { + \call_user_func(static::$onMasterStop); + } + exit(0); + } + + /** + * Execute reload. + * + * @return void + */ + protected static function reload() + { + // For master process. + if (static::$_masterPid === \posix_getpid()) { + if (static::$_gracefulStop) { + $sig = \SIGUSR2; + } else { + $sig = \SIGUSR1; + } + // Set reloading state. + if (static::$_status !== static::STATUS_RELOADING && static::$_status !== static::STATUS_SHUTDOWN) { + static::log("Workerman[" . \basename(static::$_startFile) . "] reloading"); + static::$_status = static::STATUS_RELOADING; + // Try to emit onMasterReload callback. + if (static::$onMasterReload) { + try { + \call_user_func(static::$onMasterReload); + } catch (\Exception $e) { + static::stopAll(250, $e); + } catch (\Error $e) { + static::stopAll(250, $e); + } + static::initId(); + } + + // Send reload signal to all child processes. + $reloadable_pid_array = array(); + foreach (static::$_pidMap as $worker_id => $worker_pid_array) { + $worker = static::$_workers[$worker_id]; + if ($worker->reloadable) { + foreach ($worker_pid_array as $pid) { + $reloadable_pid_array[$pid] = $pid; + } + } else { + foreach ($worker_pid_array as $pid) { + // Send reload signal to a worker process which reloadable is false. + \posix_kill($pid, $sig); + } + } + } + + // Get all pids that are waiting reload. + static::$_pidsToRestart = \array_intersect(static::$_pidsToRestart, $reloadable_pid_array); + + } + + // Reload complete. + if (empty(static::$_pidsToRestart)) { + if (static::$_status !== static::STATUS_SHUTDOWN) { + static::$_status = static::STATUS_RUNNING; + } + return; + } + // Continue reload. + $one_worker_pid = \current(static::$_pidsToRestart); + // Send reload signal to a worker process. + \posix_kill($one_worker_pid, $sig); + // If the process does not exit after static::$stopTimeout seconds try to kill it. + if(!static::$_gracefulStop){ + Timer::add(static::$stopTimeout, '\posix_kill', array($one_worker_pid, \SIGKILL), false); + } + } // For child processes. + else { + \reset(static::$_workers); + $worker = \current(static::$_workers); + // Try to emit onWorkerReload callback. + if ($worker->onWorkerReload) { + try { + \call_user_func($worker->onWorkerReload, $worker); + } catch (\Exception $e) { + static::stopAll(250, $e); + } catch (\Error $e) { + static::stopAll(250, $e); + } + } + + if ($worker->reloadable) { + static::stopAll(); + } + } + } + + /** + * Stop all. + * + * @param int $code + * @param string $log + */ + public static function stopAll($code = 0, $log = '') + { + if ($log) { + static::log($log); + } + + static::$_status = static::STATUS_SHUTDOWN; + // For master process. + if (\DIRECTORY_SEPARATOR === '/' && static::$_masterPid === \posix_getpid()) { + static::log("Workerman[" . \basename(static::$_startFile) . "] stopping ..."); + $worker_pid_array = static::getAllWorkerPids(); + // Send stop signal to all child processes. + if (static::$_gracefulStop) { + $sig = \SIGQUIT; + } else { + $sig = \SIGINT; + } + foreach ($worker_pid_array as $worker_pid) { + if (static::$daemonize) { + \posix_kill($worker_pid, $sig); + } else { + Timer::add(1, '\posix_kill', array($worker_pid, $sig), false); + } + if(!static::$_gracefulStop){ + Timer::add(static::$stopTimeout, '\posix_kill', array($worker_pid, \SIGKILL), false); + } + } + Timer::add(1, "\\Workerman\\Worker::checkIfChildRunning"); + // Remove statistics file. + if (\is_file(static::$_statisticsFile)) { + @\unlink(static::$_statisticsFile); + } + } // For child processes. + else { + // Execute exit. + $workers = array_reverse(static::$_workers); + foreach ($workers as $worker) { + if(!$worker->stopping){ + $worker->stop(); + $worker->stopping = true; + } + } + if (!static::$_gracefulStop || ConnectionInterface::$statistics['connection_count'] <= 0) { + static::$_workers = array(); + if (static::$globalEvent) { + static::$globalEvent->destroy(); + } + + try { + exit($code); + } catch (Exception $e) { + + } + } + } + } + + /** + * check if child processes is really running + */ + public static function checkIfChildRunning() + { + foreach (static::$_pidMap as $worker_id => $worker_pid_array) { + foreach ($worker_pid_array as $pid => $worker_pid) { + if (!\posix_kill($pid, 0)) { + unset(static::$_pidMap[$worker_id][$pid]); + } + } + } + } + + /** + * Get process status. + * + * @return number + */ + public static function getStatus() + { + return static::$_status; + } + + /** + * If stop gracefully. + * + * @return bool + */ + public static function getGracefulStop() + { + return static::$_gracefulStop; + } + + /** + * Write statistics data to disk. + * + * @return void + */ + protected static function writeStatisticsToStatusFile() + { + // For master process. + if (static::$_masterPid === \posix_getpid()) { + $all_worker_info = array(); + foreach(static::$_pidMap as $worker_id => $pid_array) { + /** @var /Workerman/Worker $worker */ + $worker = static::$_workers[$worker_id]; + foreach($pid_array as $pid) { + $all_worker_info[$pid] = array('name' => $worker->name, 'listen' => $worker->getSocketName()); + } + } + + \file_put_contents(static::$_statisticsFile, \serialize($all_worker_info)."\n", \FILE_APPEND); + $loadavg = \function_exists('sys_getloadavg') ? \array_map('round', \sys_getloadavg(), array(2,2,2)) : array('-', '-', '-'); + \file_put_contents(static::$_statisticsFile, + "----------------------------------------------GLOBAL STATUS----------------------------------------------------\n", \FILE_APPEND); + \file_put_contents(static::$_statisticsFile, + 'Workerman version:' . static::VERSION . " PHP version:" . \PHP_VERSION . "\n", \FILE_APPEND); + \file_put_contents(static::$_statisticsFile, 'start time:' . \date('Y-m-d H:i:s', + static::$_globalStatistics['start_timestamp']) . ' run ' . \floor((\time() - static::$_globalStatistics['start_timestamp']) / (24 * 60 * 60)) . ' days ' . \floor(((\time() - static::$_globalStatistics['start_timestamp']) % (24 * 60 * 60)) / (60 * 60)) . " hours \n", + FILE_APPEND); + $load_str = 'load average: ' . \implode(", ", $loadavg); + \file_put_contents(static::$_statisticsFile, + \str_pad($load_str, 33) . 'event-loop:' . static::getEventLoopName() . "\n", \FILE_APPEND); + \file_put_contents(static::$_statisticsFile, + \count(static::$_pidMap) . ' workers ' . \count(static::getAllWorkerPids()) . " processes\n", + \FILE_APPEND); + \file_put_contents(static::$_statisticsFile, + \str_pad('worker_name', static::$_maxWorkerNameLength) . " exit_status exit_count\n", \FILE_APPEND); + foreach (static::$_pidMap as $worker_id => $worker_pid_array) { + $worker = static::$_workers[$worker_id]; + if (isset(static::$_globalStatistics['worker_exit_info'][$worker_id])) { + foreach (static::$_globalStatistics['worker_exit_info'][$worker_id] as $worker_exit_status => $worker_exit_count) { + \file_put_contents(static::$_statisticsFile, + \str_pad($worker->name, static::$_maxWorkerNameLength) . " " . \str_pad($worker_exit_status, + 16) . " $worker_exit_count\n", \FILE_APPEND); + } + } else { + \file_put_contents(static::$_statisticsFile, + \str_pad($worker->name, static::$_maxWorkerNameLength) . " " . \str_pad(0, 16) . " 0\n", + \FILE_APPEND); + } + } + \file_put_contents(static::$_statisticsFile, + "----------------------------------------------PROCESS STATUS---------------------------------------------------\n", + \FILE_APPEND); + \file_put_contents(static::$_statisticsFile, + "pid\tmemory " . \str_pad('listening', static::$_maxSocketNameLength) . " " . \str_pad('worker_name', + static::$_maxWorkerNameLength) . " connections " . \str_pad('send_fail', 9) . " " + . \str_pad('timers', 8) . \str_pad('total_request', 13) ." qps status\n", \FILE_APPEND); + + \chmod(static::$_statisticsFile, 0722); + + foreach (static::getAllWorkerPids() as $worker_pid) { + \posix_kill($worker_pid, \SIGIOT); + } + return; + } + + // For child processes. + \gc_collect_cycles(); + if (\function_exists('gc_mem_caches')) { + \gc_mem_caches(); + } + \reset(static::$_workers); + /** @var \Workerman\Worker $worker */ + $worker = current(static::$_workers); + $worker_status_str = \posix_getpid() . "\t" . \str_pad(round(memory_get_usage(false) / (1024 * 1024), 2) . "M", 7) + . " " . \str_pad($worker->getSocketName(), static::$_maxSocketNameLength) . " " + . \str_pad(($worker->name === $worker->getSocketName() ? 'none' : $worker->name), static::$_maxWorkerNameLength) + . " "; + $worker_status_str .= \str_pad(ConnectionInterface::$statistics['connection_count'], 11) + . " " . \str_pad(ConnectionInterface::$statistics['send_fail'], 9) + . " " . \str_pad(static::$globalEvent->getTimerCount(), 7) + . " " . \str_pad(ConnectionInterface::$statistics['total_request'], 13) . "\n"; + \file_put_contents(static::$_statisticsFile, $worker_status_str, \FILE_APPEND); + } + + /** + * Write statistics data to disk. + * + * @return void + */ + protected static function writeConnectionsStatisticsToStatusFile() + { + // For master process. + if (static::$_masterPid === \posix_getpid()) { + \file_put_contents(static::$_statisticsFile, "--------------------------------------------------------------------- WORKERMAN CONNECTION STATUS --------------------------------------------------------------------------------\n", \FILE_APPEND); + \file_put_contents(static::$_statisticsFile, "PID Worker CID Trans Protocol ipv4 ipv6 Recv-Q Send-Q Bytes-R Bytes-W Status Local Address Foreign Address\n", \FILE_APPEND); + \chmod(static::$_statisticsFile, 0722); + foreach (static::getAllWorkerPids() as $worker_pid) { + \posix_kill($worker_pid, \SIGIO); + } + return; + } + + // For child processes. + $bytes_format = function($bytes) + { + if($bytes > 1024*1024*1024*1024) { + return round($bytes/(1024*1024*1024*1024), 1)."TB"; + } + if($bytes > 1024*1024*1024) { + return round($bytes/(1024*1024*1024), 1)."GB"; + } + if($bytes > 1024*1024) { + return round($bytes/(1024*1024), 1)."MB"; + } + if($bytes > 1024) { + return round($bytes/(1024), 1)."KB"; + } + return $bytes."B"; + }; + + $pid = \posix_getpid(); + $str = ''; + \reset(static::$_workers); + $current_worker = current(static::$_workers); + $default_worker_name = $current_worker->name; + + /** @var \Workerman\Worker $worker */ + foreach(TcpConnection::$connections as $connection) { + /** @var \Workerman\Connection\TcpConnection $connection */ + $transport = $connection->transport; + $ipv4 = $connection->isIpV4() ? ' 1' : ' 0'; + $ipv6 = $connection->isIpV6() ? ' 1' : ' 0'; + $recv_q = $bytes_format($connection->getRecvBufferQueueSize()); + $send_q = $bytes_format($connection->getSendBufferQueueSize()); + $local_address = \trim($connection->getLocalAddress()); + $remote_address = \trim($connection->getRemoteAddress()); + $state = $connection->getStatus(false); + $bytes_read = $bytes_format($connection->bytesRead); + $bytes_written = $bytes_format($connection->bytesWritten); + $id = $connection->id; + $protocol = $connection->protocol ? $connection->protocol : $connection->transport; + $pos = \strrpos($protocol, '\\'); + if ($pos) { + $protocol = \substr($protocol, $pos+1); + } + if (\strlen($protocol) > 15) { + $protocol = \substr($protocol, 0, 13) . '..'; + } + $worker_name = isset($connection->worker) ? $connection->worker->name : $default_worker_name; + if (\strlen($worker_name) > 14) { + $worker_name = \substr($worker_name, 0, 12) . '..'; + } + $str .= \str_pad($pid, 9) . \str_pad($worker_name, 16) . \str_pad($id, 10) . \str_pad($transport, 8) + . \str_pad($protocol, 16) . \str_pad($ipv4, 7) . \str_pad($ipv6, 7) . \str_pad($recv_q, 13) + . \str_pad($send_q, 13) . \str_pad($bytes_read, 13) . \str_pad($bytes_written, 13) . ' ' + . \str_pad($state, 14) . ' ' . \str_pad($local_address, 22) . ' ' . \str_pad($remote_address, 22) ."\n"; + } + if ($str) { + \file_put_contents(static::$_statisticsFile, $str, \FILE_APPEND); + } + } + + /** + * Check errors when current process exited. + * + * @return void + */ + public static function checkErrors() + { + if (static::STATUS_SHUTDOWN !== static::$_status) { + $error_msg = static::$_OS === \OS_TYPE_LINUX ? 'Worker['. \posix_getpid() .'] process terminated' : 'Worker process terminated'; + $errors = error_get_last(); + if ($errors && ($errors['type'] === \E_ERROR || + $errors['type'] === \E_PARSE || + $errors['type'] === \E_CORE_ERROR || + $errors['type'] === \E_COMPILE_ERROR || + $errors['type'] === \E_RECOVERABLE_ERROR) + ) { + $error_msg .= ' with ERROR: ' . static::getErrorType($errors['type']) . " \"{$errors['message']} in {$errors['file']} on line {$errors['line']}\""; + } + static::log($error_msg); + } + } + + /** + * Get error message by error code. + * + * @param integer $type + * @return string + */ + protected static function getErrorType($type) + { + if(isset(self::$_errorType[$type])) { + return self::$_errorType[$type]; + } + + return ''; + } + + /** + * Log. + * + * @param string $msg + * @return void + */ + public static function log($msg) + { + $msg = $msg . "\n"; + if (!static::$daemonize) { + static::safeEcho($msg); + } + \file_put_contents((string)static::$logFile, \date('Y-m-d H:i:s') . ' ' . 'pid:' + . (static::$_OS === \OS_TYPE_LINUX ? \posix_getpid() : 1) . ' ' . $msg, \FILE_APPEND | \LOCK_EX); + } + + /** + * Safe Echo. + * @param string $msg + * @param bool $decorated + * @return bool + */ + public static function safeEcho($msg, $decorated = false) + { + $stream = static::outputStream(); + if (!$stream) { + return false; + } + if (!$decorated) { + $line = $white = $green = $end = ''; + if (static::$_outputDecorated) { + $line = "\033[1A\n\033[K"; + $white = "\033[47;30m"; + $green = "\033[32;40m"; + $end = "\033[0m"; + } + $msg = \str_replace(array('', '', ''), array($line, $white, $green), $msg); + $msg = \str_replace(array('', '', ''), $end, $msg); + } elseif (!static::$_outputDecorated) { + return false; + } + \fwrite($stream, $msg); + \fflush($stream); + return true; + } + + /** + * @param resource|null $stream + * @return bool|resource + */ + private static function outputStream($stream = null) + { + if (!$stream) { + $stream = static::$_outputStream ? static::$_outputStream : \STDOUT; + } + if (!$stream || !\is_resource($stream) || 'stream' !== \get_resource_type($stream)) { + return false; + } + $stat = \fstat($stream); + if (!$stat) { + return false; + } + if (($stat['mode'] & 0170000) === 0100000) { + // file + static::$_outputDecorated = false; + } else { + static::$_outputDecorated = + static::$_OS === \OS_TYPE_LINUX && + \function_exists('posix_isatty') && + \posix_isatty($stream); + } + return static::$_outputStream = $stream; + } + + /** + * Construct. + * + * @param string $socket_name + * @param array $context_option + */ + public function __construct($socket_name = '', array $context_option = array()) + { + // Save all worker instances. + $this->workerId = \spl_object_hash($this); + static::$_workers[$this->workerId] = $this; + static::$_pidMap[$this->workerId] = array(); + + // Get autoload root path. + $backtrace = \debug_backtrace(); + $this->_autoloadRootPath = \dirname($backtrace[0]['file']); + Autoloader::setRootPath($this->_autoloadRootPath); + + // Context for socket. + if ($socket_name) { + $this->_socketName = $socket_name; + if (!isset($context_option['socket']['backlog'])) { + $context_option['socket']['backlog'] = static::DEFAULT_BACKLOG; + } + $this->_context = \stream_context_create($context_option); + } + + // Turn reusePort on. + /*if (static::$_OS === \OS_TYPE_LINUX // if linux + && \version_compare(\PHP_VERSION,'7.0.0', 'ge') // if php >= 7.0.0 + && \version_compare(php_uname('r'), '3.9', 'ge') // if kernel >=3.9 + && \strtolower(\php_uname('s')) !== 'darwin' // if not Mac OS + && strpos($socket_name,'unix') !== 0) { // if not unix socket + + $this->reusePort = true; + }*/ + } + + + /** + * Listen. + * + * @throws Exception + */ + public function listen() + { + if (!$this->_socketName) { + return; + } + + // Autoload. + Autoloader::setRootPath($this->_autoloadRootPath); + + if (!$this->_mainSocket) { + + $local_socket = $this->parseSocketAddress(); + + // Flag. + $flags = $this->transport === 'udp' ? \STREAM_SERVER_BIND : \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN; + $errno = 0; + $errmsg = ''; + // SO_REUSEPORT. + if ($this->reusePort) { + \stream_context_set_option($this->_context, 'socket', 'so_reuseport', 1); + } + + // Create an Internet or Unix domain server socket. + $this->_mainSocket = \stream_socket_server($local_socket, $errno, $errmsg, $flags, $this->_context); + if (!$this->_mainSocket) { + throw new Exception($errmsg); + } + + if ($this->transport === 'ssl') { + \stream_socket_enable_crypto($this->_mainSocket, false); + } elseif ($this->transport === 'unix') { + $socket_file = \substr($local_socket, 7); + if ($this->user) { + \chown($socket_file, $this->user); + } + if ($this->group) { + \chgrp($socket_file, $this->group); + } + } + + // Try to open keepalive for tcp and disable Nagle algorithm. + if (\function_exists('socket_import_stream') && static::$_builtinTransports[$this->transport] === 'tcp') { + \set_error_handler(function(){}); + $socket = \socket_import_stream($this->_mainSocket); + \socket_set_option($socket, \SOL_SOCKET, \SO_KEEPALIVE, 1); + \socket_set_option($socket, \SOL_TCP, \TCP_NODELAY, 1); + \restore_error_handler(); + } + + // Non blocking. + \stream_set_blocking($this->_mainSocket, false); + } + + $this->resumeAccept(); + } + + /** + * Unlisten. + * + * @return void + */ + public function unlisten() { + $this->pauseAccept(); + if ($this->_mainSocket) { + \set_error_handler(function(){}); + \fclose($this->_mainSocket); + \restore_error_handler(); + $this->_mainSocket = null; + } + } + + /** + * Parse local socket address. + * + * @throws Exception + */ + protected function parseSocketAddress() { + if (!$this->_socketName) { + return; + } + // Get the application layer communication protocol and listening address. + list($scheme, $address) = \explode(':', $this->_socketName, 2); + // Check application layer protocol class. + if (!isset(static::$_builtinTransports[$scheme])) { + $scheme = \ucfirst($scheme); + $this->protocol = \substr($scheme,0,1)==='\\' ? $scheme : 'Protocols\\' . $scheme; + if (!\class_exists($this->protocol)) { + $this->protocol = "Workerman\\Protocols\\$scheme"; + if (!\class_exists($this->protocol)) { + throw new Exception("class \\Protocols\\$scheme not exist"); + } + } + + if (!isset(static::$_builtinTransports[$this->transport])) { + throw new Exception('Bad worker->transport ' . \var_export($this->transport, true)); + } + } else { + $this->transport = $scheme; + } + //local socket + return static::$_builtinTransports[$this->transport] . ":" . $address; + } + + /** + * Pause accept new connections. + * + * @return void + */ + public function pauseAccept() + { + if (static::$globalEvent && false === $this->_pauseAccept && $this->_mainSocket) { + static::$globalEvent->del($this->_mainSocket, EventInterface::EV_READ); + $this->_pauseAccept = true; + } + } + + /** + * Resume accept new connections. + * + * @return void + */ + public function resumeAccept() + { + // Register a listener to be notified when server socket is ready to read. + if (static::$globalEvent && true === $this->_pauseAccept && $this->_mainSocket) { + if ($this->transport !== 'udp') { + static::$globalEvent->add($this->_mainSocket, EventInterface::EV_READ, array($this, 'acceptConnection')); + } else { + static::$globalEvent->add($this->_mainSocket, EventInterface::EV_READ, array($this, 'acceptUdpConnection')); + } + $this->_pauseAccept = false; + } + } + + /** + * Get socket name. + * + * @return string + */ + public function getSocketName() + { + return $this->_socketName ? \lcfirst($this->_socketName) : 'none'; + } + + /** + * Run worker instance. + * + * @return void + * @throws Exception + */ + public function run() + { + $this->listen(); + + // Try to emit onWorkerStart callback. + if ($this->onWorkerStart) { + try { + \call_user_func($this->onWorkerStart, $this); + } catch (\Exception $e) { + // Avoid rapid infinite loop exit. + sleep(1); + static::stopAll(250, $e); + } catch (\Error $e) { + // Avoid rapid infinite loop exit. + sleep(1); + static::stopAll(250, $e); + } + } + } + + /** + * Stop current worker instance. + * + * @return void + */ + public function stop() + { + // Try to emit onWorkerStop callback. + if ($this->onWorkerStop) { + try { + \call_user_func($this->onWorkerStop, $this); + } catch (\Exception $e) { + static::stopAll(250, $e); + } catch (\Error $e) { + static::stopAll(250, $e); + } + } + // Remove listener for server socket. + $this->unlisten(); + // Close all connections for the worker. + if (!static::$_gracefulStop) { + foreach ($this->connections as $connection) { + $connection->close(); + } + } + // Remove worker. + foreach(static::$_workers as $key => $one_worker) { + if ($one_worker->workerId === $this->workerId) { + unset(static::$_workers[$key]); + } + } + + // Clear callback. + $this->onMessage = $this->onClose = $this->onError = $this->onBufferDrain = $this->onBufferFull = null; + } + + /** + * Accept a connection. + * + * @param resource $socket + * @return void + */ + public function acceptConnection($socket) + { + // Accept a connection on server socket. + \set_error_handler(function(){}); + $new_socket = \stream_socket_accept($socket, 0, $remote_address); + \restore_error_handler(); + + // Thundering herd. + if (!$new_socket) { + return; + } + + // TcpConnection. + $connection = new TcpConnection($new_socket, $remote_address); + $this->connections[$connection->id] = $connection; + $connection->worker = $this; + $connection->protocol = $this->protocol; + $connection->transport = $this->transport; + $connection->onMessage = $this->onMessage; + $connection->onClose = $this->onClose; + $connection->onError = $this->onError; + $connection->onBufferDrain = $this->onBufferDrain; + $connection->onBufferFull = $this->onBufferFull; + + // Try to emit onConnect callback. + if ($this->onConnect) { + try { + \call_user_func($this->onConnect, $connection); + } catch (\Exception $e) { + static::stopAll(250, $e); + } catch (\Error $e) { + static::stopAll(250, $e); + } + } + } + + /** + * For udp package. + * + * @param resource $socket + * @return bool + */ + public function acceptUdpConnection($socket) + { + \set_error_handler(function(){}); + $recv_buffer = \stream_socket_recvfrom($socket, static::MAX_UDP_PACKAGE_SIZE, 0, $remote_address); + \restore_error_handler(); + if (false === $recv_buffer || empty($remote_address)) { + return false; + } + // UdpConnection. + $connection = new UdpConnection($socket, $remote_address); + $connection->protocol = $this->protocol; + if ($this->onMessage) { + try { + if ($this->protocol !== null) { + /** @var \Workerman\Protocols\ProtocolInterface $parser */ + $parser = $this->protocol; + if ($parser && \method_exists($parser, 'input')) { + while ($recv_buffer !== '') { + $len = $parser::input($recv_buffer, $connection); + if ($len === 0) + return true; + $package = \substr($recv_buffer, 0, $len); + $recv_buffer = \substr($recv_buffer, $len); + $data = $parser::decode($package, $connection); + if ($data === false) + continue; + \call_user_func($this->onMessage, $connection, $data); + } + } else { + $data = $parser::decode($recv_buffer, $connection); + // Discard bad packets. + if ($data === false) + return true; + \call_user_func($this->onMessage, $connection, $data); + } + } else { + \call_user_func($this->onMessage, $connection, $recv_buffer); + } + ++ConnectionInterface::$statistics['total_request']; + } catch (\Exception $e) { + static::stopAll(250, $e); + } catch (\Error $e) { + static::stopAll(250, $e); + } + } + return true; + } + + /** + * Check master process is alive + * + * @param int $master_pid + * @return bool + */ + protected static function checkMasterIsAlive($master_pid) + { + if (empty($master_pid)) { + return false; + } + + $master_is_alive = $master_pid && \posix_kill((int) $master_pid, 0) && \posix_getpid() !== $master_pid; + if (!$master_is_alive) { + return false; + } + + $cmdline = "/proc/{$master_pid}/cmdline"; + if (!is_readable($cmdline) || empty(static::$processTitle)) { + return true; + } + + $content = file_get_contents($cmdline); + if (empty($content)) { + return true; + } + + return stripos($content, static::$processTitle) !== false || stripos($content, 'php') !== false; + } +} + diff --git a/cacme/vendor/workerman/workerman/composer.json b/cacme/vendor/workerman/workerman/composer.json new file mode 100644 index 0000000..19e2984 --- /dev/null +++ b/cacme/vendor/workerman/workerman/composer.json @@ -0,0 +1,38 @@ +{ + "name": "workerman/workerman", + "type": "library", + "keywords": [ + "event-loop", + "asynchronous" + ], + "homepage": "http://www.workerman.net", + "license": "MIT", + "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/walkor/workerman/issues", + "forum": "http://wenda.workerman.net/", + "wiki": "http://doc.workerman.net/", + "source": "https://github.com/walkor/workerman" + }, + "require": { + "php": ">=7.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "autoload": { + "psr-4": { + "Workerman\\": "./" + } + }, + "minimum-stability": "dev" +} diff --git a/cacme/vendor/yzh52521/easyhttp/LICENSE b/cacme/vendor/yzh52521/easyhttp/LICENSE new file mode 100644 index 0000000..8cc32f9 --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014-present rap2hpoutre + +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/cacme/vendor/yzh52521/easyhttp/README.md b/cacme/vendor/yzh52521/easyhttp/README.md new file mode 100644 index 0000000..17354cd --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/README.md @@ -0,0 +1,415 @@ +EasyHttp 是一个轻量级、语义化、对IDE友好的HTTP客户端,支持常见的HTTP请求、异步请求和并发请求,让你可以快速地使用 HTTP 请求与其他 Web 应用进行通信。 + +> EasyHttp并不强制依赖于cURL,如果没有安装cURL,EasyHttp会自动选择使用PHP流处理,或者你也可以提供自己的发送HTTP请求的处理方式。 + +如果您觉得EasyHttp对您有用的话,别忘了给点个赞哦^_^ ! + +github:[github.com/yzh52521/easyhttp](https://github.com/yzh52521/easyhttp "github.com/yzh52521/easyhttp") + +gitee:[gitee.com/yzh52521/easyhttp](https://gitee.com/yzh52521/easyhttp "gitee.com/yzh52521/easyhttp") + +本包是基于 [ gouguoyin/easyhttp ](https://gitee.com/gouguoyin/easyhttp "gitee.com/gouguoyin/easyhttp") 进行扩展开发,主要实现了以下扩展: + +1. 增加 retry() 重试机制。 +2. 增加 debug 日志调试功能。 +3. 增加 withHost 指定服务端base_url +4. 增加 withBody 发送原始数据(Raw)请求 +5. 增加 withMiddleware/withRequestMiddleware/withResponseMiddleware Guzzle 中间件 +6. 增加 connectTimeout 设置等待服务器响应超时 +7. 增加 sink 响应的主体部分将要保存的位置 +8. 增加 maxRedirects 请求的重定向行为最大次数 + + +# 安装说明 + +#### 环境依赖 + +- PHP >= 7.2.5 +- 如果使用PHP流处理,allow_url_fopen 必须在php.ini中启用。 +- 如果使用cURL处理,cURL >= 7.19.4,并且编译了OpenSSL 与 zlib。 + +#### 一键安装 + + composer require yzh52521/easyhttp + +## 发起请求 + +#### 同步请求 + +###### 常规请求 + +```php +$response = Http::get('http://httpbin.org/get'); + +$response = Http::get('http://httpbin.org/get?name=yzh52521'); + +$response = Http::get('http://httpbin.org/get?name=yzh52521', ['age' => 18]); + +$response = Http::post('http://httpbin.org/post'); + +$response = Http::post('http://httpbin.org/post', ['name' => 'yzh52521']); + +$response = Http::patch(...); + +$response = Http::put(...); + +$response = Http::delete(...); + +$response = Http::head(...); + +$response = Http::options(...); + +``` + +###### 指定服务端base_url的请求 + +```php +// 指定服务端base_url地址,最终请求地址为 https://serv.yzh52521.com/login +$response = Http::withHost('https://serv.yzh52521.com')->post('/login'); + +``` +##### 发送原始数据(Raw)请求 +```php +$response = Http::withBody( + base64_encode($photo), 'image/jpeg' +)->post(...); +``` +###### 发送 Content-Type 编码请求 + +```php +// application/x-www-form-urlencoded(默认) +$response = Http::asForm()->post(...); + +// application/json +$response = Http::asJson()->post(...); +``` + +###### 发送 Multipart 表单请求 + +```php +$response = Http::asMultipart( + 'file_input_name', file_get_contents('photo1.jpg'), 'photo2.jpg' +)->post('http://test.com/attachments'); + +$response = Http::asMultipart( + 'file_input_name', fopen('photo1.jpg', 'r'), 'photo2.jpg' +)->post(...); + +$response = Http::attach( + 'file_input_name', file_get_contents('photo1.jpg'), 'photo2.jpg' +)->post(...); + +$response = Http::attach( + 'file_input_name', fopen('photo1.jpg', 'r'), 'photo2.jpg' +)->post(...); +``` +> 表单enctype属性需要设置成 multipart/form-data + +###### 携带请求头的请求 + +```php +$response = Http::withHeaders([ + 'x-powered-by' => 'yzh52521' +])->post(...); +``` + +###### 携带重定向的请求 + +```php +// 默认 +$response = Http::withRedirect(false)->post(...); + +$response = Http::withRedirect([ + 'max' => 5, + 'strict' => false, + 'referer' => true, + 'protocols' => ['http', 'https'], + 'track_redirects' => false +])->post(...); + +$response = Http::maxRedirects(5)->post(...); +``` + + + +###### 携带认证的请求 + +```php +// Basic认证 +$response = Http::withBasicAuth('username', 'password')->post(...); + +// Digest认证(需要被HTTP服务器支持) +$response = Http::withDigestAuth('username', 'password')->post(...); +``` + +###### 携带 User-Agent 的请求 +```php +$response = Http::withUA('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36')->post(...); +``` + +###### 携带Token令牌的请求 + +```php +$response = Http::withToken('token')->post(...); +``` + +###### 携带认证文件的请求 + +```php +$response = Http::withCert('/path/server.pem', 'password')->post(...); +``` + +###### 携带SSL证书的请求 + +```php +// 默认 +$response = Http::withVerify(false)->post(...); + +$response = Http::withVerify('/path/to/cert.pem')->post(...); +``` + +###### 携带COOKIE的请求 + +```php +$response = Http::withCookies(array $cookies, string $domain)->post(...); +``` + +###### 携带协议版本的请求 + +```php +$response = Http::withVersion(1.1)->post(...); +``` + +###### 携带代理的请求 + +```php +$response = Http::withProxy('tcp://localhost:8125')->post(...); + +$response = Http::withProxy([ + 'http' => 'tcp://localhost:8125', // Use this proxy with "http" + 'https' => 'tcp://localhost:9124', // Use this proxy with "https", + 'no' => ['.com.cn', 'yzh52521.cn'] // Don't use a proxy with these +])->post(...); +``` + +###### 设置超时时间(单位秒) + +```php +$response = Http::timeout(60)->post(...); +``` + +###### 设置等待服务器响应超时的最大值(单位秒) + +```php +$response = Http::connectTimeout(60)->post(...); +``` + +###### 设置延迟时间(单位秒) + +```php +$response = Http::delay(60)->post(...); +``` + +###### 设置并发次数 + +```php +$response = Http::concurrency(10)->promise(...); +``` + +###### 重发请求,设置retry方法。重试次数/两次重试之间的时间间隔(毫秒): + +```php +$response = Http::retry(3, 100)->post(...); +``` +##### 响应的主体部分将要保存的位置 +```php +$response = Http::sink('/path/to/file')->post(...); +``` + +#### Guzzle 中间件 + +```php +use GuzzleHttp\Middleware; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +$response = Http::withMiddleware( + Middleware::mapRequest(function (RequestInterface $request) { + $request = $request->withHeader('X-Example', 'Value'); + return $request; + }) +)->get('http://example.com'); + +……………… +$response = Http::withRequestMiddleware( + function (RequestInterface $request) { + $request = $request->withHeader('X-Example', 'Value'); + return $request; + } +)->get('http://example.com'); + +……………… + +$response = Http::withResponseMiddleware( + function (RequestInterface $response) { + $response = $response->getHeader('X-Example'); + return $response; + } +)->get('http://example.com'); +``` + +#### 异步请求 + +```php +use yzh52521\EasyHttp\Response; +use yzh52521\EasyHttp\RequestException; + +$promise = Http::getAsync('http://easyhttp.yzh52521.cn/api/sleep3.json', ['token' => TOKEN], function (Response $response) { + echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL; +}, function (RequestException $e) { + echo '异步请求异常,错误码:' . $e->getCode() . ',错误信息:' . $e->getMessage() . PHP_EOL; +}); + +$promise->wait(); +echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL; + +//输出 +{"code":200,"msg":"请求成功"} +异步请求成功,响应内容:{"code":200,"msg":"success","second":3} + +$promise = Http::getAsync('http1://easyhttp.yzh52521.cn/api/sleep3.json', function (Response $response) { + echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL; +}, function (RequestException $e) { + echo '异步请求异常,错误信息:' . $e->getMessage() . PHP_EOL; +}); + +$promise->wait(); +echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL; + +//输出 +{"code":200,"msg":"请求成功"} +异步请求异常,错误信息:cURL error 1: Protocol "http1" not supported or disabled in libcurl (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) + +Http::postAsync(...); + +Http::patchAsync(...); + +Http::putAsync(...); + +Http::deleteAsync(...); + +Http::headAsync(...); + +Http::optionsAsync(...); + +使用 等待异步回调处理完成 +Http::wait(); +``` + +#### 异步并发请求 + +```php +use yzh52521\EasyHttp\Response; +use yzh52521\EasyHttp\RequestException; + +$promises = [ + Http::getAsync('http://easyhttp.yzh52521.cn/api/sleep3.json'), + Http::getAsync('http1://easyhttp.yzh52521.cn/api/sleep1.json', ['name' => 'yzh52521']), + Http::postAsync('http://easyhttp.yzh52521.cn/api/sleep2.json', ['name' => 'yzh52521']), +]; + +$pool=Http::concurrency(10)->multiAsync($promises, function (Response $response, $index) { + echo "发起第 $index 个异步请求,请求时长:" . $response->json()->second . '秒' . PHP_EOL; +}, function (RequestException $e, $index) { + echo "发起第 $index 个请求失败,失败原因:" . $e->getMessage() . PHP_EOL; +}); + +$promise = $pool->promise(); +$promise->wait(); + +//输出 +发起第 1 个请求失败,失败原因:cURL error 1: Protocol "http1" not supported or disabled in libcurl (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) +发起第 2 个异步请求,请求时长:2 秒 +发起第 0 个异步请求,请求时长:3 秒 +``` +> 如果未调用concurrency()方法,并发次数默认为$promises的元素个数,$promises数组里必须是异步请求 + +## 使用响应 + +发起请求后会返回一个 yzh52521\EasyHttp\Response $response的实例,该实例提供了以下方法来检查请求的响应: + +```php +$response->body() : string; +$response->json() : object; +$response->array() : array; +$response->status() : int; +$response->ok() : bool; +$response->successful() : bool; +$response->serverError() : bool; +$response->clientError() : bool; +$response->headers() : array; +$response->header($header) : string; +``` + +## 异常处理 + +请求在发生客户端或服务端错误时会抛出 yzh52521\EasyHttp\RequestException $e异常,该实例提供了以下方法来返回异常信息: + +```php +$e->getCode() : int; +$e->getMessage() : string; +$e->getFile() : string; +$e->getLine() : int; +$e->getTrace() : array; +$e->getTraceAsString() : string; +``` +## 调试日志 + +有时候难免要对 Http 的请求和响应包体进行记录以方便查找问题或做什么 + +```php +//传递一个日志类 thinkphp \think\facade\Log laravel Illuminate\Support\Facades\Log +Http::debug(Log::class)->post(...); +``` + + +## 更新日志 +### 2023-08-31 +* 新增 withBody 可以发送原始数据(Raw)请求 +* 新增 withMiddleware/withRequestMiddleware/withResponseMiddleware 支持Guzzle中间件 +* 新增 connectTimeout 设置等待服务器响应超时 +* 新增 sink 响应的主体部分将要保存的位置 +* 新增 maxRedirects 请求的重定向行为最大次数 +### 2022-05-11 +* 新增removeBodyFormat() 用于withOptions 指定body时,清除原由的bodyFromat +### 2022-05-10 +* 新增发送原生请求的方法client() +* 新增发送原生异步请求的方法clientASync() +### 2021-09-03 +* 新增 debug() 调试日志 +* 新增 retry() 重试机制 +* 修复header重叠的bug +### 2020-03-30 +* 修复部分情况下IDE不能智能提示的BUG +* get()、getAsync()方法支持带参数的url +* 新增withUA()方法 +* 新增withStream()方法 +* 新增asMultipart()方法,attach()的别名 +* 新增multiAsync()异步并发请求方法 + +### 2020-03-20 +* 新增异步请求getAsync()方法 +* 新增异步请求postAsync()方法 +* 新增异步请求patchAsync()方法 +* 新增异步请求putAsync()方法 +* 新增异步请求deleteAsync()方法 +* 新增异步请求headAsync()方法 +* 新增异步请求optionsAsync()方法 + +## Todo List + - [x] 异步请求 + - [x] 并发请求 + - [x] 重试机制 + - [ ] 支持http2 + - [ ] 支持swoole +# easyhttp diff --git a/cacme/vendor/yzh52521/easyhttp/composer.json b/cacme/vendor/yzh52521/easyhttp/composer.json new file mode 100644 index 0000000..862a47f --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/composer.json @@ -0,0 +1,33 @@ +{ + "name": "yzh52521/easyhttp", + "description": "EasyHttp 是一个轻量级、语义化、对IDE友好的HTTP客户端,支持常见的HTTP请求、异步请求和并发请求,让你可以快速地使用 HTTP 请求与其他 Web 应用进行通信。", + "license": "MIT", + "keywords": [ + "easyhttp", + "EasyHttp", + "php-http", + "phphttp", + "easy-http", + "php", + "http", + "curl" + ], + "homepage": "https://github.com/yzh52521/easyhttp", + "authors": [ + { + "name": "yzh52521", + "email": "396751927@qq.com" + } + ], + "require": { + "php": ">=7.2.5", + "guzzlehttp/guzzle": "^6.0|^7.0", + "psr/log":"^1.0|^2.0|^3.0" + }, + "autoload": { + "psr-4": { + "yzh52521\\EasyHttp\\": "src/" + } + }, + "minimum-stability": "stable" +} diff --git a/cacme/vendor/yzh52521/easyhttp/src/ConnectionException.php b/cacme/vendor/yzh52521/easyhttp/src/ConnectionException.php new file mode 100644 index 0000000..cdbf363 --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/src/ConnectionException.php @@ -0,0 +1,10 @@ +facade = new $this->facade; + } + + public function __call($name, $params) + { + if (method_exists($this->facade, 'removeOptions')) { + call_user_func_array([$this->facade, 'removeOptions'], []); + } + return call_user_func_array([$this->facade, $name], $params); + } + + public static function __callStatic($name, $params) + { + return call_user_func_array([new static(), $name], $params); + } +} diff --git a/cacme/vendor/yzh52521/easyhttp/src/Http.php b/cacme/vendor/yzh52521/easyhttp/src/Http.php new file mode 100644 index 0000000..4685e05 --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/src/Http.php @@ -0,0 +1,64 @@ +setLogger($logger); + $this->setFormatter($formatter ?: $this->getDefaultFormatter()); + } + + /** + * Returns the default formatter; + * + * @return MessageFormatter + */ + protected function getDefaultFormatter() + { + return new MessageFormatter(); + } + + /** + * Sets whether requests should be logged before the response is received. + * + * @param boolean $logRequests + */ + public function setRequestLoggingEnabled($logRequests = true) + { + $this->logRequests = (bool) $logRequests; + } + + /** + * Sets the logger, which can be a PSR-3 logger or a callable that accepts + * a log level, message, and array context. + * + * @param LoggerInterface|callable $logger + * + * @throws InvalidArgumentException + */ + public function setLogger($logger) + { + if ($logger instanceof LoggerInterface || is_callable($logger)) { + $this->logger = $logger; + } else { + throw new InvalidArgumentException( + "Logger has to be a Psr\Log\LoggerInterface or callable" + ); + } + } + + /** + * Sets the formatter, which can be a MessageFormatter or callable that + * accepts a request, response, and a reason if an error has occurred. + * + * @param MessageFormatter|callable $formatter + * + * @throws InvalidArgumentException + */ + public function setFormatter($formatter) + { + if ($formatter instanceof MessageFormatter || is_callable($formatter)) { + $this->formatter = $formatter; + } else { + throw new InvalidArgumentException( + "Formatter has to be a \GuzzleHttp\MessageFormatter or callable" + ); + } + } + + /** + * Sets the log level to use, which can be either a string or a callable + * that accepts a response (which could be null). A log level could also + * be null, which indicates that the default log level should be used. + * + * @param string|callable|null + */ + public function setLogLevel($logLevel) + { + $this->logLevel = $logLevel; + } + + /** + * Logs a request and/or a response. + * + * @param RequestInterface $request + * @param ResponseInterface|null $response + * @param $reason + * @return mixed + */ + protected function log( + RequestInterface $request, + ResponseInterface $response = null, + $reason = null + ) { + if ($reason instanceof RequestException) { + $response = $reason->getResponse(); + } + + $level = $this->getLogLevel($response); + $message = $this->getLogMessage($request, $response, $reason); + $context = compact('request', 'response', 'reason'); + + // Make sure that the content of the body is available again. + if ($response) { + $response->getBody()->seek(0);; + } + + if (is_callable($this->logger)) { + return call_user_func($this->logger, $level, $message, $context); + } + + $this->logger->log($level, $message, $context); + } + + /** + * Formats a request and response as a log message. + * + * @param RequestInterface $request + * @param ResponseInterface|null $response + * @param mixed $reason + * + * @return string The formatted message. + */ + protected function getLogMessage( + RequestInterface $request, + ResponseInterface $response = null, + $reason = null + ) { + if ($this->formatter instanceof MessageFormatter) { + return $this->formatter->format( + $request, + $response, + $reason + ); + } + + return call_user_func($this->formatter, $request, $response, $reason); + } + + /** + * Returns a log level for a given response. + * + * @param ResponseInterface $response The response being logged. + * + * @return string LogLevel + */ + protected function getLogLevel(ResponseInterface $response = null) + { + if ( ! $this->logLevel) { + return $this->getDefaultLogLevel($response); + } + + if (is_callable($this->logLevel)) { + return call_user_func($this->logLevel, $response); + } + + return (string) $this->logLevel; + } + + /** + * Returns the default log level for a response. + * + * @param ResponseInterface $response + * + * @return string LogLevel + */ + protected function getDefaultLogLevel(ResponseInterface $response = null) { + if ($response && $response->getStatusCode() >= 300) { + return LogLevel::NOTICE; + } + + return LogLevel::INFO; + } + + /** + * Returns a function which is handled when a request was successful. + * + * @param RequestInterface $request + * + * @return \Closure + */ + protected function onSuccess(RequestInterface $request) + { + return function ($response) use ($request) { + $this->log($request, $response); + return $response; + }; + } + + /** + * Returns a function which is handled when a request was rejected. + * + * @param RequestInterface $request + * + * @return \Closure + */ + protected function onFailure(RequestInterface $request) + { + return function ($reason) use ($request) { + + // Only log a rejected request if it hasn't already been logged. + if ( ! $this->logRequests) { + $this->log($request, null, $reason); + } + + return Promise\rejection_for($reason); + }; + } + + /** + * Called when the middleware is handled by the client. + * + * @param callable $handler + * + * @return \Closure + */ + public function __invoke(callable $handler) + { + return function ($request, array $options) use ($handler) { + + // Only log requests if explicitly set to do so + if ($this->logRequests) { + $this->log($request); + } + + return $handler($request, $options)->then( + $this->onSuccess($request), + $this->onFailure($request) + ); + }; + } +} diff --git a/cacme/vendor/yzh52521/easyhttp/src/Request.php b/cacme/vendor/yzh52521/easyhttp/src/Request.php new file mode 100644 index 0000000..a84df3d --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/src/Request.php @@ -0,0 +1,711 @@ +client = $this->getInstance(); + + $this->bodyFormat = 'form_params'; + $this->options = [ + 'http_errors' => false, + ]; + $this->handlerStack = HandlerStack::create(new CurlHandler()); + } + + /** + * Request destructor. + */ + public function __destruct() + { + + } + + /** + * 获取单例 + * @return mixed + */ + public function getInstance() + { + $name = get_called_class(); + + if (!isset(self::$instances[$name])) { + self::$instances[$name] = new Client(); + } + + return self::$instances[$name]; + } + + public function removeOptions() + { + $this->bodyFormat = 'form_params'; + $this->isRemoveBodyFormat = false; + $this->options = [ + 'http_errors' => false, + 'verify' => false + ]; + return $this; + } + + public function asForm() + { + $this->bodyFormat = 'form_params'; + $this->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded']); + + return $this; + } + + public function asJson() + { + $this->bodyFormat = 'json'; + $this->withHeaders(['Content-Type' => 'application/json']); + + return $this; + } + + public function asMultipart(string $name, string $contents, string $filename = null, array $headers = []) + { + $this->bodyFormat = 'multipart'; + + $this->options = array_filter([ + 'name' => $name, + 'contents' => $contents, + 'headers' => $headers, + 'filename' => $filename, + ]); + + return $this; + } + + public function withMiddleware(callable $middleware) + { + $this->handlerStack->push($middleware); + + $this->options['handler'] = $this->handlerStack; + + return $this; + } + + public function withRequestMiddleware(callable $middleware) + { + $this->handlerStack->push(Middleware::mapRequest($middleware)); + + $this->options['handler'] = $this->handlerStack; + + return $this; + } + + public function withResponseMiddleware(callable $middleware) + { + $this->handlerStack->push(Middleware::mapResponse($middleware)); + + $this->options['handler'] = $this->handlerStack; + + return $this; + } + + public function withHost(string $host) + { + $this->options['base_uri'] = $host; + + return $this; + } + + public function withOptions(array $options) + { + unset($this->options[$this->bodyFormat], $this->options['body']); + + $this->options = array_merge_recursive($this->options, $options); + + return $this; + } + + public function withCert(string $path, string $password) + { + $this->options['cert'] = [$path, $password]; + + return $this; + } + + public function withHeaders(array $headers) + { + $this->options = array_merge_recursive($this->options, [ + 'headers' => $headers, + ]); + + return $this; + } + + public function withBody($content, $contentType = 'application/json') + { + $this->bodyFormat = 'body'; + + $this->options['headers']['Content-Type'] = $contentType; + + $this->pendingBody = $content; + + return $this; + } + + public function withBasicAuth(string $username, string $password) + { + $this->options['auth'] = [$username, $password]; + + return $this; + } + + public function withDigestAuth(string $username, string $password) + { + $this->options['auth'] = [$username, $password, 'digest']; + + return $this; + } + + public function withUA(string $ua) + { + $this->options['headers']['User-Agent'] = trim($ua); + + return $this; + } + + public function withToken(string $token, string $type = 'Bearer') + { + $this->options['headers']['Authorization'] = trim($type . ' ' . $token); + + return $this; + } + + public function withCookies(array $cookies, string $domain) + { + $this->options = array_merge_recursive($this->options, [ + 'cookies' => CookieJar::fromArray($cookies, $domain), + ]); + + return $this; + } + + public function withProxy($proxy) + { + $this->options['proxy'] = $proxy; + + return $this; + } + + public function withVersion($version) + { + $this->options['version'] = $version; + + return $this; + } + + public function maxRedirects(int $max) + { + $this->options['allow_redirects']['max'] = $max; + + return $this; + } + + public function withRedirect($redirect = false) + { + $this->options['allow_redirects'] = $redirect; + + return $this; + } + + public function withVerify($verify = false) + { + $this->options['verify'] = $verify; + + return $this; + } + + public function withStream($boolean = false) + { + $this->options['stream'] = $boolean; + + return $this; + } + + public function concurrency(int $times) + { + $this->concurrency = $times; + + return $this; + } + + public function retry(int $retries = 1, int $sleep = 0) + { + $this->handlerStack->push((new Retry())->handle($retries, $sleep)); + + $this->options['handler'] = $this->handlerStack; + + return $this; + } + + public function delay(int $seconds) + { + $this->options['delay'] = $seconds * 1000; + + return $this; + } + + public function timeout(float $seconds) + { + $this->options['timeout'] = $seconds; + + return $this; + } + + public function connectTimeout(float $seconds) + { + $this->options['connect_timeout'] = $seconds; + + return $this; + } + + /** + * @param string|resource $to + * @return $this + */ + public function sink($to) + { + $this->options['sink'] = $to; + + return $this; + } + + public function removeBodyFormat() + { + $this->isRemoveBodyFormat = true; + return $this; + } + + public function debug($class) + { + $logger = new Logger(function ($level, $message, array $context) use ($class) { + $class::log($level, $message); + }, function ($request, $response, $reason) { + $requestBody = $request->getBody(); + $requestBody->rewind(); + + //请求头 + $requestHeaders = []; + + foreach ((array)$request->getHeaders() as $k => $vs) { + foreach ($vs as $v) { + $requestHeaders[] = "$k: $v"; + } + } + + //响应头 + $responseHeaders = []; + + foreach ((array)$response->getHeaders() as $k => $vs) { + foreach ($vs as $v) { + $responseHeaders[] = "$k: $v"; + } + } + + $uri = $request->getUri(); + $path = $uri->getPath(); + + if ($query = $uri->getQuery()) { + $path .= '?' . $query; + } + + return sprintf( + "Request %s\n%s %s HTTP/%s\r\n%s\r\n\r\n%s\r\n--------------------\r\nHTTP/%s %s %s\r\n%s\r\n\r\n%s", + $uri, + $request->getMethod(), + $path, + $request->getProtocolVersion(), + join("\r\n", $requestHeaders), + $requestBody->getContents(), + $response->getProtocolVersion(), + $response->getStatusCode(), + $response->getReasonPhrase(), + join("\r\n", $responseHeaders), + $response->getBody()->getContents() + ); + }); + $this->handlerStack->push($logger); + $this->options['handler'] = $this->handlerStack; + + return $this; + } + + public function attach(string $name, string $contents, string $filename = null, array $headers = []) + { + $this->options['multipart'] = array_filter([ + 'name' => $name, + 'contents' => $contents, + 'headers' => $headers, + 'filename' => $filename, + ]); + + return $this; + } + + public function get(string $url, array $query = []) + { + $params = parse_url($url, PHP_URL_QUERY); + + parse_str($params ?: '', $result); + + $this->options['query'] = array_merge($result, $query); + + return $this->request('GET', $url, $query); + } + + public function post(string $url, array $data = []) + { + $this->options[$this->bodyFormat] = $data; + + return $this->request('POST', $url, $data); + } + + public function patch(string $url, array $data = []) + { + $this->options[$this->bodyFormat] = $data; + + return $this->request('PATCH', $url, $data); + } + + public function put(string $url, array $data = []) + { + $this->options[$this->bodyFormat] = $data; + + return $this->request('PUT', $url, $data); + } + + public function delete(string $url, array $data = []) + { + $this->options[$this->bodyFormat] = $data; + + return $this->request('DELETE', $url, $data); + } + + public function head(string $url, array $data = []) + { + $this->options[$this->bodyFormat] = $data; + + return $this->request('HEAD', $url, $data); + } + + public function options(string $url, array $data = []) + { + $this->options[$this->bodyFormat] = $data; + + return $this->request('OPTIONS', $url, $data); + } + + public function getAsync(string $url, $query = null, callable $success = null, callable $fail = null) + { + is_callable($query) || $this->options['query'] = $query; + + return $this->requestAsync('GET', $url, $query, $success, $fail); + } + + public function postAsync(string $url, $data = null, callable $success = null, callable $fail = null) + { + is_callable($data) || $this->options[$this->bodyFormat] = $data; + + return $this->requestAsync('POST', $url, $data, $success, $fail); + } + + public function patchAsync(string $url, $data = null, callable $success = null, callable $fail = null) + { + is_callable($data) || $this->options[$this->bodyFormat] = $data; + + return $this->requestAsync('PATCH', $url, $data, $success, $fail); + } + + public function putAsync(string $url, $data = null, callable $success = null, callable $fail = null) + { + is_callable($data) || $this->options[$this->bodyFormat] = $data; + + return $this->requestAsync('PUT', $url, $data, $success, $fail); + } + + public function deleteAsync(string $url, $data = null, callable $success = null, callable $fail = null) + { + is_callable($data) || $this->options[$this->bodyFormat] = $data; + + return $this->requestAsync('DELETE', $url, $data, $success, $fail); + } + + public function headAsync(string $url, $data = null, callable $success = null, callable $fail = null) + { + is_callable($data) || $this->options[$this->bodyFormat] = $data; + + return $this->requestAsync('HEAD', $url, $data, $success, $fail); + } + + public function optionsAsync(string $url, $data = null, callable $success = null, callable $fail = null) + { + is_callable($data) || $this->options[$this->bodyFormat] = $data; + + return $this->requestAsync('OPTIONS', $url, $data, $success, $fail); + } + + public function multiAsync(array $promises, callable $success = null, callable $fail = null) + { + $count = count($promises); + + $this->concurrency = $this->concurrency ?: $count; + + $requests = function () use ($promises) { + foreach ($promises as $promise) { + yield function () use ($promise) { + return $promise; + }; + } + }; + + $fulfilled = function ($response, $index) use ($success) { + if (!is_null($success)) { + $response = $this->response($response); + call_user_func_array($success, [$response, $index]); + } + }; + + $rejected = function ($exception, $index) use ($fail) { + if (!is_null($fail)) { + $exception = $this->exception($exception); + call_user_func_array($fail, [$exception, $index]); + } + }; + + $pool = new Pool($this->client, $requests(), [ + 'concurrency' => $this->concurrency, + 'fulfilled' => $fulfilled, + 'rejected' => $rejected, + ]); + + $pool->promise(); + + return $pool; + } + + protected function request(string $method, string $url, array $options = []) + { + if (isset($this->options[$this->bodyFormat])) { + $this->options[$this->bodyFormat] = $options; + } else { + $this->options[$this->bodyFormat] = $this->pendingBody; + } + if ($this->isRemoveBodyFormat) { + unset($this->options[$this->bodyFormat]); + } + try { + $response = $this->client->request($method, $url, $this->options); + return $this->response($response); + } catch (ConnectException $e) { + throw new ConnectionException($e->getMessage(), 0, $e); + } + } + + /** + * 原生请求 + * @param string $method + * @param string $url + * @param array $options + * @return Response + * @throws ConnectionException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function client(string $method, string $url, array $options = []) + { + if (isset($this->options[$this->bodyFormat])) { + $this->options[$this->bodyFormat] = $options; + } else { + $this->options[$this->bodyFormat] = $this->pendingBody; + } + if ($this->isRemoveBodyFormat) { + unset($this->options[$this->bodyFormat]); + } + try { + if (empty($options)) { + $options = $this->options; + } + $response = $this->client->request($method, $url, $options); + return $this->response($response); + } catch (ConnectException $e) { + throw new ConnectionException($e->getMessage(), 0, $e); + } + } + + /** + * 原生异步请求 + * @param string $method + * @param string $url + * @param array $options + * @return Response + * @throws ConnectionException + */ + public function clientAsync(string $method, string $url, array $options = []) + { + if (isset($this->options[$this->bodyFormat])) { + $this->options[$this->bodyFormat] = $options; + } else { + $this->options[$this->bodyFormat] = $this->pendingBody; + } + if ($this->isRemoveBodyFormat) { + unset($this->options[$this->bodyFormat]); + } + try { + if (empty($options)) { + $options = $this->options; + } + $response = $this->client->requestAsync($method, $url, $options); + return $this->response($response); + } catch (ConnectException $e) { + throw new ConnectionException($e->getMessage(), 0, $e); + } + } + + + protected function requestAsync(string $method, string $url, $options = null, callable $success = null, callable $fail = null) + { + if (is_callable($options)) { + $successCallback = $options; + $failCallback = $success; + } else { + $successCallback = $success; + $failCallback = $fail; + } + + if (isset($this->options[$this->bodyFormat])) { + $this->options[$this->bodyFormat] = $options; + } else { + $this->options[$this->bodyFormat] = $this->pendingBody; + } + + if ($this->isRemoveBodyFormat) { + unset($this->options[$this->bodyFormat]); + } + + try { + $promise = $this->client->requestAsync($method, $url, $this->options); + + $fulfilled = function ($response) use ($successCallback) { + if (!is_null($successCallback)) { + $response = $this->response($response); + call_user_func_array($successCallback, [$response]); + } + }; + + $rejected = function ($exception) use ($failCallback) { + if (!is_null($failCallback)) { + $exception = $this->exception($exception); + call_user_func_array($failCallback, [$exception]); + } + }; + + $promise->then($fulfilled, $rejected); + + $this->promises[] = $promise; + + return $promise; + } catch (ConnectException $e) { + throw new ConnectionException($e->getMessage(), 0, $e); + } + } + + public function wait() + { + if (!empty($this->promises)) { + \GuzzleHttp\Promise\Utils($this->promises)->wait(); + } + $this->promises = []; + } + + protected function response($response) + { + return new Response($response); + } + + protected function exception($exception) + { + return new RequestException($exception); + } + +} diff --git a/cacme/vendor/yzh52521/easyhttp/src/RequestException.php b/cacme/vendor/yzh52521/easyhttp/src/RequestException.php new file mode 100644 index 0000000..29b1dca --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/src/RequestException.php @@ -0,0 +1,43 @@ +exception = $exception; + } + + public function getCode() + { + return $this->exception->getCode(); + } + + public function getMessage() + { + return $this->exception->getMessage(); + } + + public function getFile() + { + return $this->exception->getFile(); + } + + public function getLine() + { + return $this->exception->getLine(); + } + + public function getTrace() + { + return $this->exception->getTrace(); + } + + public function getTraceAsString() + { + return $this->exception->getTraceAsString(); + } +} diff --git a/cacme/vendor/yzh52521/easyhttp/src/Response.php b/cacme/vendor/yzh52521/easyhttp/src/Response.php new file mode 100644 index 0000000..73d7f02 --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/src/Response.php @@ -0,0 +1,212 @@ +response = $response; + } + + /** + * Get the body of the response. + * @return string + */ + public function body() + { + return (string)$this->response->getBody(); + } + + /** + * Get the Array decoded body of the response. + * @return array|mixed + */ + public function array() + { + if (!$this->decoded) { + $this->decoded = json_decode( (string)$this->response->getBody(),true ); + } + + return $this->decoded; + } + + /** + * Get the JSON decoded body of the response. + * @return object|mixed + */ + public function json() + { + if (!$this->decoded) { + $this->decoded = json_decode( (string)$this->response->getBody() ); + } + + return $this->decoded; + } + + /** + * Get a header from the response. + * @param string $header + * @return mixed + */ + public function header(string $header) + { + return $this->response->getHeaderLine( $header ); + } + + /** + * Get the headers from the response. + * @return mixed + */ + public function headers() + { + return $this->mapWithKeys( $this->response->getHeaders(),function ($v,$k) { + return [$k => $v]; + } )->response; + } + + /** + * Get the status code of the response. + * @return int + */ + public function status() + { + return (int)$this->response->getStatusCode(); + } + + /** + * Determine if the request was successful. + * @return bool + */ + public function successful() + { + return $this->status() >= 200 && $this->status() < 300; + } + + /** + * Determine if the response code was "OK". + * @return bool + */ + public function ok() + { + return $this->status() === 200; + } + + /** + * Determine if the response was a redirect. + * @return bool + */ + public function redirect() + { + return $this->status() >= 300 && $this->status() < 400; + } + + /** + * Determine if the response indicates a client error occurred. + * @return bool + */ + public function clientError() + { + return $this->status() >= 400 && $this->status() < 500; + } + + /** + * Determine if the response indicates a server error occurred. + * @return bool + */ + public function serverError() + { + return $this->status() >= 500; + } + + /** + * Determine if the given offset exists. + * + * @param string $offset + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetExists($offset) + { + return array_key_exists( $offset,$this->json() ); + } + + /** + * Get the value for a given offset. + * + * @param string $offset + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->json()[$offset]; + } + + /** + * Set the value at the given offset. + * + * @param string $offset + * @param mixed $value + * @return void + * + * @throws \LogicException + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset,$value) + { + throw new LogicException( 'Response data may not be mutated using array access.' ); + } + + /** + * Unset the value at the given offset. + * + * @param string $offset + * @return void + * + * @throws \LogicException + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + throw new LogicException( 'Response data may not be mutated using array access.' ); + } + + /** + * Get the body of the response. + * + * @return string + */ + public function __toString() + { + return $this->body(); + } + + protected function mapWithKeys($items,callable $callback) + { + $result = []; + + foreach ( $items as $key => $value ) { + $assoc = $callback( $value,$key ); + + foreach ( $assoc as $mapKey => $mapValue ) { + $result[$mapKey] = $mapValue; + } + } + + return new static( $result ); + } + +} diff --git a/cacme/vendor/yzh52521/easyhttp/src/Retry.php b/cacme/vendor/yzh52521/easyhttp/src/Retry.php new file mode 100644 index 0000000..e9982a7 --- /dev/null +++ b/cacme/vendor/yzh52521/easyhttp/src/Retry.php @@ -0,0 +1,46 @@ +decider($retries), $this->delay($sleep)); + } + + protected function decider(int $times) + { + return function ( + $retries, + Request $request, + Response $response = null, + RequestException $exception = null + ) use ($times) { + // 超过最大重试次数,不再重试 + if ($retries >= $times) { + return false; + } + return $exception instanceof ConnectException || $exception instanceof ServerException || ($response && $response->getStatusCode() >= 500); + }; + } + + /** + * 返回一个匿名函数,该匿名函数返回下次重试的时间(毫秒) + * @param int $retry_delay + * @return \Closure + */ + protected function delay(int $retry_delay) + { + return function ($retries) use ($retry_delay) { + return $retry_delay * $retries; + }; + } +} diff --git a/cacme/webman b/cacme/webman new file mode 100755 index 0000000..69758c1 --- /dev/null +++ b/cacme/webman @@ -0,0 +1,57 @@ +#!/usr/bin/env php +setName('webman cli'); +$cli->installInternalCommands(); +if (is_dir($command_path = Util::guessPath(app_path(), '/command', true))) { + $cli->installCommands($command_path); +} + +foreach (config('plugin', []) as $firm => $projects) { + if (isset($projects['app'])) { + if ($command_str = Util::guessPath(base_path() . "/plugin/$firm", 'command')) { + $command_path = base_path() . "/plugin/$firm/$command_str"; + $cli->installCommands($command_path, "plugin\\$firm\\$command_str"); + } + } + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['command'] ?? [] as $class_name) { + $reflection = new \ReflectionClass($class_name); + if ($reflection->isAbstract()) { + continue; + } + $properties = $reflection->getStaticProperties(); + $name = $properties['defaultName']; + if (!$name) { + throw new RuntimeException("Command {$class_name} has no defaultName"); + } + $description = $properties['defaultDescription'] ?? ''; + $command = Container::get($class_name); + $command->setName($name)->setDescription($description); + $cli->add($command); + } + } +} + +$cli->run(); diff --git a/cacme/windows.bat b/cacme/windows.bat new file mode 100644 index 0000000..f07ce53 --- /dev/null +++ b/cacme/windows.bat @@ -0,0 +1,3 @@ +CHCP 65001 +php windows.php +pause \ No newline at end of file diff --git a/cacme/windows.php b/cacme/windows.php new file mode 100644 index 0000000..21fa888 --- /dev/null +++ b/cacme/windows.php @@ -0,0 +1,118 @@ +load(); + } else { + Dotenv::createMutable(base_path())->load(); + } +} + +App::loadAllConfig(['route']); + +$errorReporting = config('app.error_reporting'); +if (isset($errorReporting)) { + error_reporting($errorReporting); +} + +$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows'; +if (!is_dir($runtimeProcessPath)) { + mkdir($runtimeProcessPath); +} +$processFiles = [ + __DIR__ . DIRECTORY_SEPARATOR . 'start.php' +]; +foreach (config('process', []) as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, ''); +} + +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['process'] ?? [] as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name"); + } + } + foreach ($projects['process'] ?? [] as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm); + } +} + +function write_process_file($runtimeProcessPath, $processName, $firm): string +{ + $processParam = $firm ? "plugin.$firm.$processName" : $processName; + $configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']"; + $fileContent = << true]); + if (!$resource) { + exit("Can not execute $cmd\r\n"); + } + return $resource; +} + +$resource = popen_processes($processFiles); +echo "\r\n"; +while (1) { + sleep(1); + if (!empty($monitor) && $monitor->checkAllFilesChange()) { + $status = proc_get_status($resource); + $pid = $status['pid']; + shell_exec("taskkill /F /T /PID $pid"); + proc_close($resource); + $resource = popen_processes($processFiles); + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..1b2d470 --- /dev/null +++ b/index.html @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + 来笙实验室 - Laysense Website + + + + + + + + + +
+
+
+
+

Laysense Lab
来笙实验室

+
+
+
+
+
+ +
+
+ +
©上海来笙信息科技有限公司 Shanghai Laysense Information Technology Co Ltd.
沪ICP备2024051698号-1

+
+ + + \ No newline at end of file diff --git a/xb.php b/xb.php new file mode 100644 index 0000000..3f67aed --- /dev/null +++ b/xb.php @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + 来笙实验室 - Laysense Website + + + + + + + + + + +
+
+

Binance Launchpad 新币价格计算器

+

By Laysense Inslight Global

+

BinanceAPI Status: + + msg.' '.round($response[1]*1000,2).'ms'); + +$maininfo=apiGet('https://binanceapi.mirrorsite.eu.org/bapi/lending/v1/friendly/launchpool/project/listV3?page=1')[0]; +$coininfo=$maininfo->data->tracking; +if(!isset($coininfo)||$coininfo==[]||$coininfo==''){ + die('目前没有正在开展的新币挖矿'); +}else{ + $coininfo=$coininfo[0]; +} +if($coininfo->projects[0]->asset=='FDUSD'&&isset($coininfo->projects[1])&&$coininfo->projects[1]->asset=='BNB'){ +$detail['fdusd']=$coininfo->projects[0]; +$detail['bnb']=$coininfo->projects[1]; +}elseif(isset($coininfo->projects[1])){ + $detail['fdusd']=$coininfo->projects[1]; + $detail['bnb']=$coininfo->projects[0]; +}else{ + $detail['bnb']=$coininfo->projects[0]; + #$detail['fdusd']=$coininfo->projects[1]; + +} +$ratelist=apiGet('https://binanceapi.mirrorsite.eu.org/bapi/margin/v1/friendly/margin/asset/all'); +$bnbinfo=array(); +$bnbinfo['price']=apiGet('https://binanceapi.mirrorsite.eu.org/api/v3/avgPrice?symbol=BNBUSDT')[0]->price; +$bnbinfo['amount']=$detail['bnb']->totalInvestAmount; +$bnbinfo['new']=$detail['bnb']->rebateTotalAmount; +$bnbinfo['rad']=$detail['bnb']->shareRatio; +$bnbinfo['rate']=apiGet('https://binanceapi.mirrorsite.eu.org/sapi/v1/margin/crossMarginData'.sign('coin=BNB'))[0][0]->dailyInterest; + +$fdinfo['amount']=$detail['fdusd']->totalInvestAmount; +$fdinfo['new']=$detail['fdusd']->rebateTotalAmount; +$fdinfo['rad']=$detail['fdusd']->shareRatio; +$fdinfo['rate']=apiGet('https://binanceapi.mirrorsite.eu.org/sapi/v1/simple-earn/flexible/list'.sign('asset=FDUSD'))[0]->rows[0]->latestAnnualPercentageRate; +$fdinfo['rate']=round($bnbinfo['rate']/365,5); + + +$best=($bnbinfo['amount']*$bnbinfo['price']*$bnbinfo['rate']*$coininfo->duration)/$bnbinfo['new']; +$worst=(($bnbinfo['amount']*$bnbinfo['price']*$bnbinfo['rate']*$coininfo->duration)/$coininfo->rebateTotalAmount)*$bnbinfo['rad']+(($fdinfo['amount']*$fdinfo['rate']*$coininfo->duration)/$coininfo->rebateTotalAmount)*$fdinfo['rad']; +?> +

+ +
+ +
+
+
+
+ +
+ + + + +
+
+ + + +
+
+
+
    +
  • + 新币名称
    + REZ + + + rebateCoin);?> + +
  • +
  • + 新币总量 + +
  • +
  • + 挖矿天数 + +
  • +
  • + 结束日期
    + + mineEndTime));?> + +
  • + +
  • + 当前BNB年化利率(%) + +
  • +
  • + 当前BNB市场价格($) + +
  • +
  • + 当前BNB抵押数量(枚) + +
  • +
  • + 当前BNB抵押价值($) + +
  • +
  • + BNB矿池代币(新币) + +
  • + +
  • + 当前FDUSD年化利率(%) + +
  • +
  • + 当前FDUSD抵押数量(枚) + +
  • +
  • + FDUSD占比(%) + +
  • +
  • + FDUSD矿池代币(新币) + +
  • +
  • + 最低估价($) + +
  • +
  • + 最佳估价($) + +
  • + + +
  • + 您投入的BNB数量 + +
  • +
  • + 您投入的FDUSD数量 + +
  • +
  • + 获取新币数量 + +
  • +
  • + 最低价值($) + +
  • +
  • + 最高价值($) + +
  • +
  • + 最低ARR(%) + +
  • +
  • + 最高ARR(%) + +
  • +
+
+
+
+ + +
+ +
+ + + + \ No newline at end of file